Android开发艺术探索笔记 第四章
View的工作原理
基本概念
- ViewRoot对英语ViewRootImpl类,他是连接WindowManager和DecorView的纽带
- View的绘制流程是从ViewRoot的performTraversals方法开始的,该方法依次调用performMeasure,performLayout, performDraw。先进行顶级View的measure,layout,draw方法,然后递归遍历view树
- DecorView其实是一个FrameLayout,一般情况下它内部会包含一个竖直方向的LinearLayout,上面是标题栏,下面是内容栏
- View层的事件都先传递给DecorView然后在传递给我们的View
- MesureSpec代表一个32位的int值,高2位代表SpecMode测量模式,低30位代表在该测量模式下的规格大小。设计的目的是避免过多的对象内存分配
- Exactly,精确大小,Layoutparams指定具体数值和fillparent都属于精确数值
- *Atmost,父控件指定一个大小view不能超过他,对应于LayoutParams的wrap_content
- 系统会将LayoutParams在父容器的约束下转换成对应的MeasureSpec,再根据这个MeasureSpec来确定定测量后的宽高,DecorView没有父容器,所以受窗口尺寸约束
- View采用固定宽高的时候,不管父容器的MeasureSpec是什么,View的MesureSpec都是精确模式
- View采用match_parent时,父为精确View为精确,父为最大View为最大且不能超过父容器的剩余空间
- View采用wrap_content时,不管父容器的MesureSpec是什么,View的模式总是最大,且不能超过父容器的剩余空间
- 以上可以得出结论只要给出父类的MesureSpec和子类的LayoutParams就能推出子类的MesureSpec
View的工作流程
- View的Mesure方法是final类型的,子类不能重写,但是他会调用onMesure方法
- View的最终大小是在layout阶段确定的,但是大部分情况下测量大小(MesureSpec)和最终大小是相等的
- 直接继承View的自定义控件需要重写onMesure方法并设置wrap_content时的大小,否则wrap_content,就相当于使用match_parent
- ViewGroup是一个抽象类,没有重写View的onMesure方法,需要子类去各自实现,而是有一个ViewGroup方法。思想就是取出子View的lp,算出ms传给子View
- 一个好的习惯是在onLayout中去获取View的测量宽高或者最终宽高
- View的Mesure过程和Activity的生命周期方法不是同步执行的,因此无法保证某个Activity的回掉函数时View已经测量完毕了
- 四个方法解决上面的问题1、回掉函数onWindowFcusChanged;2、View的post一个runnable;3、viewTreeObserver
- layout方法确定View本身的位置,onLayout方法确定所有子元素的位置
自定义View
- 直接继承View需要自己支持warp_content(onMeasure中处理),padding(draw中处理),直接继承Viewgroup需要自己处理测量、布局
- View提供了Post没必要使用Handler
- onDetachedFromWindow中结束动画是一个很好的时机
- Margin属性由父控件控制
- 在构造方法中解析自定义属性,TypedArray试用结束后用recycle方法回收资源
- 一个典型的schemas声明 xmlns:app=http://schemas.android.com/apk/res-auto