Android 中View的绘制流程及其自定义


绘制流程

View的绘制是从ViewRoot 的performTraversals方法开始的,流程如下(图片来自《Android开发艺术探索》):
Android 中View的绘制流程

测量

MeasureSpec

概念:MeasureSpec是一个int变量,高两位用来表示SpecMode类型,低30位用来表示SpecSize。MeasureSpec决定了持有该MeasureSpec的View的大小。每个View都持有两个MeasureSpec变量(分别用于决定宽、高)。

由来:一个View的MeasureSpec由自身的LayoutParams(其中的width、height,即xml文件中的layout_width、layout_height)和它的父布局的MeasureSpec 共同决定。创建规则如下图:
MeasureSpec的创建规则
注:顶级View(如DecorView)的MeasureSpec是由窗口尺寸和自身LayoutParams决定。

measure、onMeasure的实现

View的测量包括measure、onMeasure两个步骤。
基类**View中含有:**final measure()、onMeasure()。
基类ViewGroup:并未重写这两个方法。
onMeasure()方法会被View的子类重写(如TextView、LinearLayout。注:ViewGroup并未重写onMeasure())。
若自定义view直接继承View这一基类而不是它的子类如TextView则需要在onMeasure()中处理padding和wrap_content的情况,否则,不需重写onMeasure()。
之所以需要处理wrap_content的情况是因为基类View的onMeasure()方法直接用自身MeasureSpec的specSize决定自身大小,而从上图MeasureSpec的创建规则可知,View自身的specSize在match_parent和wrap_content的情况下都是等于parentSize即它的parentView的specSize。在基类View的onMeasure()方法中也并未对padding做任何处理。

onMeasure需要实现的功能:
1. 遍历子View:调用getChildMeasureSpec()方法(这一方法就是MeasureSpec的创建规则)获得子View的宽和高的MeasureSpec,调用子View的measure()方法。(注意:只有布局才有这一步骤)
2. 据自身的MeasureSpec 设置自身宽高

布局

**基类**View中含有:layout()、abstract onLayout()。
基类**ViewGroup:**final layout()、abstract onLayout()。

layout、onLayout需要实现的功能:
1. layout():确定自身位置。(注:与measure过程不同)
2. onLayout():遍历并调用子View的layout()

绘制

调用canvas的方法并结合Paint来画图。


自定义

自定义View就是重写onMeasure()、onLayout()、onDraw()方法。

具体参考该demo下的Custom View:具有动画效果的饼状图、条形图等

猜你喜欢

转载自blog.csdn.net/cheneasternsun/article/details/80650548
今日推荐