“我不再寻找好运,我自己就是好运。”
你这小小的碎片知识——View的绘制流程。
拿来吧你,直接美美的拿捏。
1.绘制流程
来跟我记。
- 当点击App启动的时候,启动了Activity。
- 一个Activity对应的会有三个Window,一个是关于Activity,一个是Dialog,一个是Toast。(这也是Dialog和Toast不能影响Activity的生命周期的原因)
- Window是一个抽象基类,是 Activity 和整个 View 系统交互的接口,只有一个子类实现类PhoneWindow。
- 我们显示的视图是在DecorView上。
- ViewRootImpl 就是建立 DecorView 和 Window 之间的联系。
- 整体视图情况如下:
2.主流程
当应用启动时,会启动一个主 Activity,系统会根据 Activity 的布局来对它进行绘制。绘制会从根视图 ViewRoot 的 performTraversals() 方法开始。
performTraversals 方法在类 ViewRootImpl 内,其核心代码如下。
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
...
// 测量
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
// 布局
performLayout(lp, mWidth, mHeight);
...
// 绘制
performDraw();
3.MeasureSpec(测量模式)
- UNSPECIFIED:不指定测量模式,父视图没有限制子视图的大小,子视图可以是想要的任何尺寸,通常用于系统内部,应用开发中很少使用到。
- EXACTLY:精确测量模式,当该视图的 layout_width 或者 layout_height 指定为具体数值或者 match_parent 时生效,表示父视图已经决定了子视图的精确大小,这种模式下 View 的测量值就是 SpecSize 的值。
- AT_MOST:最大值模式,当前视图的 layout_width 或者 layout_height 指定为 wrap_content 时生效,此时子视图的尺寸可以是不超过父视图运行的最大尺寸的任何尺寸。
4.Measure(测量)
- Measure 用来计算 View 的实际大小。页面的测量流程从 performMeasure 方法开始。
- 具体操作是分发给 ViewGroup 的,由 ViewGroup 在它的 measureChild 方法中传递给子 View。ViewGroup 通过遍历自身所有的子 View,并逐个调用子 View 的 measure 方法实现测量操作。
- View (ViewGroup) 的 Measure 方法,最终的测量是通过回调 onMeasure 方法实现的,这个通常由 View 的特定子类自己实现,可以通过重写这个方法实现自定义 View。
5.Layout(位置)
Layout 过程用来确定 View 在父容器的布局位置,他是父容器获取子 View 的位置参数后,调用子 View 的 layout 方法并将位置参数传入实现的。
6.Draw(绘制)
绘制基本上可以分为六个步骤。
public void draw(Canvas canvas) {
...
// Step 1, draw the background, if needed
if (!dirtyOpaque) {
drawBackground(canvas);
}
...
// Step 2, save the canvas' layers
saveCount = canvas.getSaveCount();
...
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 5, draw the fade effect and restore layers
canvas.drawRect(left, top, right, top + length, p);
...
canvas.restoreToCount(saveCount);
...
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
}
7.错误不足
请大佬私信指出。(心里默念,我是没错的)