文章目录
- 4.1 初识 ViewRoot 和 DecorView
- 4.2 理解 MeasureSpec
- 4.3 View 的工作流程
- 4.4 自定义 View
【读书笔记|《Android开发艺术探索》读书笔记--第4章 View的工作原理】
4.1 初识 ViewRoot 和 DecorView
- ViewRoot 对应于 ViewRootImpl 类,连接 WindowManager 和 DecorView 的纽带
- View 的三大流程均通过 ViewRoot 完成
ViewRoot#performTraversals
ViewGroupView
performMeasuremeasureonMeasuremeasure
performLayoutlayoutonLayoutlayout
performDrawdrawonDrawdraw
- DecorView 其实是一个 FrameLayout
4.2 理解 MeasureSpec
- MeasureSpec:一个32位int值,高2位代表SpecMode(测量模式),低30位代表SpecSize(规格大小)
模式 |
简介 |
UNSPECIFIED |
要多大就多大 |
EXACTLY |
精确模式,match_parent、具体数值 |
AT_MOST |
最大模式, wrap_content |
- 对于 DecorView ,MeasureSpec 由窗口尺寸和自身的 LayoutParams 共同决定
- 普通 View,由 父容器的 MeasureSpec 和自身 LayoutParams 决定。
结论(getChildeMeasureSpec) |
View采用固定宽/高,不管父容器 MeasureSpec 是什么,View的 MeasureSpec 都是 精确模式 |
View 为 match_parent,1.父容器是精确模式,View是精确模式,大小是父容器剩余空间;2.父容器是最大模式,View也是最大模式,大小不会超过父容器剩余空间 |
View的宽/高是wrap_content,不管父容器是精确还是最大化,View模式总是最大化,并且不能超过父容器剩余空间 |
4.3 View 的工作流程
流程 |
View |
ViewGroup |
measure(测量) |
1.measure就完成测量过程;2.measure是一个final,子类不可重写,看onMeasure ;3.onMeasure中getMeasuredWidth/Height拿到View宽高,可能不准,需要 onLayout 方法中;4.Activity/View#onWindowFocusChanged;5.view.post();6.ViewTreeObserver(getViewTreeObserver().addOnGlobalLayoutListener);
7.view.measure(补充) |
1.完成自己测量过程,还要遍历去调用所有子元素measure方法,各个子元素在measure;2.measureChildren;3.onMeasure 需要子类去重写 |
layout(布局) |
1.layout 确定 View 本身位置;2.步骤:setFrame设定View四个顶点位置,接着调用 onLayout 方法,用途是父容器确定子元素位置;3.onLayout 与具体布局有关,View 和 ViewGroup 均没有真正实现 onLayout |
|
draw(绘制) |
1.绘制背景backgroud.draw(canvas);2.绘制自己(onDraw);3.绘制children(dispatchDraw);4.绘制装饰;(onDrawScrollBars)。 5.setWillNotDraw,如果一个View不需要绘制任何内容,设置 true,系统优化 |
|
view.measure
1.具体的数值
int width = MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY)
int heigth= MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY)
view.measure(width ,heigth)2.wrap_content
int width = MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOST)
int heigth= MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOST)
view.measure(width ,heigth)
- getWidth/getMeasureWidth 区别
在View默认实现中,View测量宽/高和最终宽高相等,只不过测量宽高形成与View的measure,而最终宽高形成View的layout过程。
4.4 自定义 View
4.4.1 自定义View分类
分类 |
|
继承View重写OnDraw |
wrap_content,padding |
继承ViewGroup派生特殊Layout |
测量、布局 |
继承特定View(tv) |
|
继承特定ViewGroup(ll) |
|
须知 |
|
让View支持wrap_content |
在 onMeasure 中对 wrap_content |
如果有必要,让Viw支持padding |
draw 中处理 padding,直接继承 ViewGroup 要在 onMeasure 和 onLayout 汇总 考虑 padding 和 子元素 margin 对其造成的影响,不让导致 padding 和 子元素 margin 失效 |
尽量不要在view中使用Handler |
post |
如果有线程或动画,要及时停止,参考 View#onDetachedFromWindow |
|
View带有滑动嵌套情形时,需要处理滑动冲突 |
|
推荐阅读