View的工作流程-measure、layout、draw三大流程
2017-09-13 16:44
337 查看
measure过程
View:直接完成其测量的过程ViewGroup:测量自己和它的子元素
View的measure过程:
最开始是View的measure方法measure方法里面调用了onMeasure方法,onMeasure方法的源码为:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
它是设置View的宽高测量值。其中的getDefaultSize方法返回的是measureSpec中的SpecSize。可参考MeasureSpec的理解了解一下MeasureSpec。
getSuggestedMinimumWidth与getSuggestedMinimumHeight返回的规则是:如果View有设置背景,则返回该背景对应Drawable的原始宽高;否则返回指定的android:minWidth和android:minHeight.
getDefaultSize方法源码:
public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
从中和集合MeasureSpec的SpecMode可以注意到,如果直接继承View来自定义控件,如果没有重写onMeasure方法并设置wrap_content的自身大小,则wrap_content会默认是match_parent。
解决(套路):
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecMode=MeasureSpec.getMode(widthMeasureSpec); int heightSpecMode=MeasureSpec.getMode(heightMeasureSpec); int widthSpecSize=MeasureSpec.getSize(widthMeasureSpec); int heightSpecSize=MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode==MeasureSpec.AT_MOST && heightSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(默认的width,默认height); }else if (widthSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(默认的width,heightSpecSize); }else if (heightSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(widthSpecSize,默认的height); } }
ViewGroup的measure过程:
measureChildren方法,在此中遍历子View,调用measureChild方法对每个子View进行测量
measureChild:获取子View的MeasureSpec,然后调用每个子View的measure方法
注意:很多时候我们不知道View到底在何时测量完毕,所有在获取宽高时要采用特定的办法。
采用onWindowFocusChanged:View已经测量完毕,当Activity的窗口得到焦点或者失去焦点时均会被调用。
view.post(runnable) : 通过消息机制去获取。
ViewTreeObserver:使用它的OnGlobalLayoutListener接口,可监听View树的变化,当View的可见性发生变化时,onGlobalLayout会被调用,这时的View也是测量好的了。
自己手动调用:view.measure(int widthMeasureSpec, int heightMeasureSpec)。
Layout过程
Layout过程是用来确定View的具体位置的。1.View的layout过程
在layout方法中通过setFrame方法设定View的四个定点的位置调用onLayout方法:确定本身的位置,与onMeasure相似,都是与具体的布局有关,在View中没有具体的实现。
2.ViewGroup的layout过程
没有具体实现onLayout方法。具体的View有着不同的实现draw过程
public void draw(Canvas canvas) { final int privateFlags = mPrivateFlags; final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; // Step 1, draw the background, if needed int saveCount; if (!dirtyOpaque) { drawBackground(canvas); } // skip step 2 & 5 if possible (common case) final int viewFlags = mViewFlags; boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; if (!verticalEdges && !horizontalEdges) { // Step 3, draw the content if (!dirtyOpaque) onDraw(canvas); // Step 4, draw the children dispatchDraw(canvas); // Overlay is part of the content and draws beneath Foreground if (mOverlay != null && !mOverlay.isEmpty()) { mOverlay.getOverlayView().dispatchDraw(canvas); } // Step 6, draw decorations (foreground, scrollbars) onDrawForeground(canvas); // we're done... return; } ......
根据注释的步骤:
drawBackground(canvas):绘制背景
onDraw(canvas):绘制自己
dispatchDraw(canvas):绘制children
onDrawForeground(canvas):绘制装饰
特殊方法:setWillNotDraw(boolean willNotDraw)
该方法用来设置是否绘制内容。
true:不绘制,然后系统还会进行优化。
false:绘制。
4000
相关文章推荐
- Android自定义view之measure、layout、draw三大流程
- Android进阶系列0—View的工作流程:measure,layout,draw小结
- 安卓 View 工作流程-Measure、 Layout、Draw 源码阅读
- Android自己定义view之measure、layout、draw三大流程
- Android应用层View绘制流程之measure,layout,draw三步曲
- Android应用层View绘制流程之measure,layout,draw三步曲
- View的工作流程(layout过程)
- Android进阶——Android视图工作机制之measure、layout、draw
- (六)VIew的绘制过程-measure、layout、draw
- view工作流程解析之measure测量
- 源码分析篇 - Android绘制流程(二)measure、layout、draw流程
- View的工作原理之View的measure、layout、draw
- Android View体系(八)从源码解析View的layout和draw流程
- Android视图的绘制流程(下)——View的Layout与Draw过程
- view绘制流程之layout和draw
- View显示流程-View draw的准备工作
- 【Android源码学习】View的layout和draw流程
- View的三次measure,两次layout和一次draw
- (总结篇)Android 牛不牛?决定于自定义View控件(一)——view绘制流程(onMeasure,onLayout,onDraw)
- Android视图工作机制之measure、layout、draw