标签:
本篇模拟三个角色:Android 架构师-小福、Android 控件开发工程师-小黑、 Android 开发工程师-小白,下面按照三个角色不同角度分析measure过程。
小福负责分享:
public final class ViewRootImpl extends Handler implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks { // 1 所有子视图的requestLayout方法,最总都会触发根视图此方法 public void requestLayout() { checkThread(); // 需要重新布局 mLayoutRequested = true; scheduleTraversals(); } // 调度遍历 public void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; ..... // 当前类继承自Handler,发出一个空消息,目的是加入Message队列 sendEmptyMessage(DO_TRAVERSAL); } } @Override public void handleMessage(Message msg) { switch (msg.what) { ... case DO_TRAVERSAL: ... // 处理DO_TRAVERSAL消息 performTraversals(); ... break; ..... } } // 执行遍历 private void performTraversals() { final View host = mView; int desiredWindowWidth; int desiredWindowHeight; int childWidthMeasureSpec; int childHeightMeasureSpec; ...... if (mLayoutRequested && !mStopped) { ...... childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width); childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height); ...... // host是一个View对象 host.measure(childWidthMeasureSpec, childHeightMeasureSpec); ...... } ...... } }
接着上面的measure流程的第五步走下去,以下是android.view.View.java文件中的源码:
public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback, AccessibilityEventSource { // 方法是final类型,说明不能被覆写或者重载 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { // 如果有重新请求标志,或者宽高发生改变 if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT || widthMeasureSpec != mOldWidthMeasureSpec || heightMeasureSpec != mOldHeightMeasureSpec) { ...... // 真正执行测量视图大小操作 // measure ourselves, this should set the measured dimension flag back onMeasure(widthMeasureSpec, heightMeasureSpec); ...... // 添加重新请求子视图布局标志 mPrivateFlags |= LAYOUT_REQUIRED; } ...... } /** * Call this when something has changed which has invalidated the * layout of this view. This will schedule a layout pass of the view * tree. */ public void requestLayout() { if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT); } // 添加重新请求布局标志 mPrivateFlags |= FORCE_LAYOUT; mPrivateFlags |= INVALIDATED; if (mParent != null) { if (mLayoutParams != null) { mLayoutParams.resolveWithDirection(getResolvedLayoutDirection()); } if (!mParent.isLayoutRequested()) { mParent.requestLayout(); } } } }
上面代码的measure流程可以分为4个步骤
1 measure与requestLayout -> 2 onMeasure
紧接着看下android.widget.FrameLayout类的onMeasure总都做了什么?
类名.方法名 | 解释 |
MeasureSpec.getMode(int measureSpec) | 根据提供的测量值(格式)提取模式(上述三个模式之一) |
MeasureSpec.getSize(int measureSpec) | 根据提供的测量值(格式)提取大小值 |
MeasureSpec.makeMeasureSpec(int size,int mode) | 根据提供的大小值和模式创建一个测量值(格式) |
模式 | 翻译 | 模式与Layout参数对应关系 | 模式描述 |
UNSPECIFIED | 无限制 | parent view不约束child view的大小 | |
AT_MOST | 最多的 | wrap_content | child view可以在parent view范围内取值 |
EXACTLY | 准确的 | fill_parent(例如50dip) | parent view为child view指定固定大小 |
标签:
原文地址:http://blog.csdn.net/androiddevelop/article/details/44263731