自定义View是Android初级工程师进阶或者面试必备的一项技能,能造出各种狂拽酷炫吊炸天的自定义控件,一直以来都是我非常羡慕的一件事。要想学会自定义View,首先必须掌握的就是View的工作原理。
1. What
View,是Android所有视图的基类,小到一个TextView,或者各种复杂的布局RelativeLayout,最终都是继承自View。由此可见,掌握View的工作原理,在Android开发过程的重要性。
源码对View的解释是:
This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.). The ViewGroup subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.
View这个类表示用户界面组件的基本构建块。 View占据屏幕上的矩形区域,负责绘图和事件处理。 View是各种组件的基类,用于创建交互式UI组件(按钮,文本字段等)。 ViewGroup子类是布局的基类,它是包含其他View(或其他ViewGroups)并定义其布局属性的不可见容器。
总的来说,ViewGroup也是继承自View,View只能单独存在,ViewGroup内部可以包含一个或多个View(ViewGroup)。
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
2. Android窗口层级
先看一张示例图片,很标准的一个普通Activity
视图层级
由此可见,DecorView就是整个窗口的最外层顶级View,一般来说,DecorView会包含一个orientation为vertical的垂直方向LinearLayout,这个Layout包含上下两部分:ActionBar(Android5.0API21以后新增Toolbar)和一个id为content的FrameLayout 容器。ActivityThread中,当Activity创建完成后,会将Activity添加到Window中,同时会创建ViewRoot对象和DecorView相关联。我们最终在Activity ->onCreate方法中所写的setContentView,就是将我们定义的布局设置到这个容器进行显示。
对于Android中 Window,ViewRoot,DecorView,Activity之间的关系,请移步到:xxxx
3. View工作原理
了解了DecorView,就可以开始探索View的工作原理了。相信你看到这篇文章时,就已经知道一个控件的显示的三部曲:Measure(测量)、Layout(布局)、Draw(绘制)。
View的绘制流程就是从ViewRoot的performTraversals方法开始,该方法会依次执行performMeasure,performLayout,performDraw,每一步其实都会执行到DecorView内部的measure,layout,draw方法,最终由DecorView依次往下传递,measure方法完成后,就可以通过getMeasuredWidth()和getMeasuredHeight()方法获取测量的宽高(并不一定就是View实际显示的宽高),layout方法完成后,即可确定View显示的位置,可通过getLeft, getTop, getRight, getBottom获取左上右下四个顶点的坐标,并通过geiWidth方法(mRight - mLeft)和getHeight方法(mBottom - mTop) 获取实际宽高, draw方法就是直接将View的内容绘制显示到屏幕上。
子元素又会重复这一过程,直至完成整个窗口的绘制。下面贴上来自《Android开发艺术探索》的performTraversals流程图:
下面开始三部曲之旅:
- View的测量
- View的布局
- View的绘制