来自:《Android开发艺术探索》
控件绘制
测量 measure 确定View的测量宽高
布局 layout 确定View的最终宽高和四个顶点位置
绘制 draw 将View绘制在屏幕上
measure
如果是单一view,只需要根据父View的MeasureSpec进行大小计算。而ViewGroup除了完成自己的测量,一般要重写onMeasure方法,遍历各子元素递归测量。
这样Measure过程就从DecorView一级一级传递下去了,也就是要遍历所有子View的的尺寸,最终得出总的viewGroup的尺寸。Layout和Draw方法也是如此。
最重要的方法是getDefaultSize,根据MeasureSpec去取SpecMode和SpecSize
MeasureSpec(一个32位int值)译为测量规格
很大程度上决定了一个View的尺寸规格(普通view的measureSpec由父容器的MSLP和自身决定),测量过程中,系统会将View的LayoutParams根据父容器的规则转换成MeasureSpec(LayoutParams->MeasureSpec),再用它测量出View的宽/高。这个值的高两位代表SpecMode,低30位代表SpecSize,并提供了打包和解包的方法。
SpecMode有三种:
UNSPECIFIED:父容器对View不做任何限制,一般用于系统内部
EXACTLY:对应layoutParams中的match_parent和具体数值,意为父容器已检测出View所需的精确大小,这是view的最终大小就是SpecSize的值
AT_MOST:对应LayoutParams中的wrap_content,意为父容器制定了一个可用大小即SpecSize,View的大小只要不大于这个值就由View自己定
layout
对ViewGroup的作用在于确定子元素的位置,当ViewGroup的位置被确定后,它在onLayout中会遍历所有的子元素并调用其layout方法。单一View直接计算自己的位置,ViewGroup除了计算自己的位置还要计算子View在富容器中的位置和宽高,调用子View的onLayout方法。
draw
将View绘制到屏幕上面
(1)drawBackground()绘制背景
(2)onDraw()绘制自身
(3)dispatchDraw()绘制children
(4)onDrawScrollBars(canvas)绘制装饰
自定义控件
- 对现有的控件进行拓展(特定显示效果)
- 通过组合来实现新的控件(为了特定功能,解决多次重复使用同一类型的布局,如应用标题栏)
- 重写View来实现全新的控件