Android View 绘制流程

Android View在进行绘制之前会先进行measure和layout,我们的分析从draw开始并假设上面两步已经完成。View的绘制函数是在ViewRootImpl.java的performDraw()开始,以下就是简单调用流程图:

Android View绘制主要流程

简单总结:

1.draw(boolean fullRedrawNeeded),参数设置是否全部重新绘制,设置之后的结果就是dirty矩阵重新设置为View最大值。

2.当dirty不为空并且正在动画,则准备开始绘制View。在View绘制之前会先进行canvas设置,主要就是两部分设置屏幕密度和设置分辨率,两个方法均通过native设置。

3.现在开始绘制View,直接调用mView.draw(canvas);在View的draw(canvas)函数中实现了绘制的六个步骤,但是考虑2和5步骤不常用所以做优化处理暂不处理。接下来是绘制的关键步骤说明:

第1步:绘制背景。前提是该View背景是非透明,一般View背景都是非透明。在绘制背景之前,如果scrollX和scrollY存在值,那么先去平移canvas。在默认情况下canvas的原点是View本身的左上角位置,如果存在scrollX和scrollY,说明此时View内容发生了滚动。但是要绘制的内容或者说程序员指定的背景都是相对于View可视区域的原点,所以在绘制之前需要先做canvas平移到View可视区域的处理。然后在canvas绘制背景。

第3步:绘制View本身内容。其实质就是调用onDraw(canvas),但是前提仍然是View不是透明状态。View的该方法未实现。

第4步:ViewGroup绘制子View。首先需要说明的是在这里,这个View实际上是FrameLayout,所以该方法实际是FrameLayout需要实现的。但是我们现在只看ViewGroup最原始的实现方法。主要有如下阶段:

(1)检查是否设置了布局动画是否需要绘制缓存。在for循环中遍历所有子View设置使用的布局动画参数及对象和绘制View内容到Bitmap缓存上。在绘制到Bitmap时,首先依据参数处理缩放,然后计算缓存该View的Bitmap大小,如果过大直接返回,最后创建Bitmap并且设置为canvas绘制的对象。在绘制之前同样需要处理scrollX和scrollY,然后在检查ViewGroup是否要跳过该View的绘制,如果不是在直接执行onDraw(canvas)绘制内容到缓存。最后做动画启动前参数设置回调接口。

(2)剪裁canvas然后逐个绘制子View。首先根据ViewGroup的padding属性剪裁canvas,接下来按照一定顺序(可重写自定义)绘制子View。主要经过如下步骤:

  • 判断是否使用缓存绘制View

  • 获取View的动画对象,执行动画drawAnimation(parent, drawingTime, a, scalingRequired);在绘制动画时进行如下步骤:

1.初始化动画开始前的变量

2.获取变换对象,这个变换对象就是动画执行的依据。

3.执行重绘动画。

  • 接下来做多重判断,最主要的判断就是canvas是否在父View的剪切区:canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW);如果不在就直接返回。

  • 判断是否使用绘制缓存,如果需要使用先去绘制缓存到Bitmap。

  • 接下来就是应用变换对象到canvas,这也是之所以动画形成的主要步骤。首先处理缩放接着是变换对象最后就是透明度。

  • 接下来就是绘制View。如果使用缓存绘制,直接将Bitmap绘制到canvas。否则就回调draw(canvas);绘制。

  • 最后恢复canvas状态。判断是否是一次动画如果结束回调接口,如果动画仍然进行继续调用重绘函数。

(3)处理绘制移除但是存在动画的View。

(4)绘制debug的View。

(5)在重绘子View时如果需要重绘ViewGroup则接着重绘。

(6)判断动画结束,则回调结束接口。

第6步:绘制滚动条。

(1)获取滚动条状态,如果是OFF直接返回,如果是FADING动态改变滚动条透明度同时设置重绘标志。

(2)如果是水平滚动条,以其为例。首先获取其高度及滚动条相对于View的坐标,然后直接调用onDrawHorizontalScrollBar()绘制,其内部就是Drawable对象的绘制。如果是滚动状态需要持续调用重绘。

(4)垂直滚动类似。

至此就是View绘制的主要步骤。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值