四、视图的measure过程
这三个绘制流程中,measure是最复杂的,咱们进入performMeasure方法分析其源码,这里仅贴出关键流程代码。
1 //ViewRootImpl.java 2 private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) { 3 ...... 4 mView.measure(childWidthMeasureSpec, childHeightMeasureSpec); 5 ...... 6 }
这个mView是谁呢?跟踪代码可以找到给它赋值的地方:
//ViewRootImpl.java public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { ...... mView = view; ......
mWindowAttributes.copyFrom(attrs);
......
}
看到这里,是不是有些似曾相识呢?在第二节的绘制流程中提到过,这里setView的参数view和attrs是ActivityThread类中addView方法传递过来的,所以咱们这里可以确定mView指的是DecorView了。上述performMeasure方法中,其实就是DecorView在执行measure()操作了。如果您这存在“mView不是View类型的吗,怎么会指代DecorView作为整个View体系的跟节点呢”这样的疑惑,那这里顺便提一下,DecorView extends FrameLayout extends ViewGroup extends View,通过这个继承链可以看到,DecorView是一个容器,但ViewGroup也是View的子类,View是所有控件的基类,所以这里View类型的mView指代DecorView没毛病。
咱们继续追踪measure()方法,这部分有约60行代码,这里贴出关键流程:
1 View.java 2 /** 3 * <p> 4 * This is called to find out how big a view should be. The parent 5 * supplies constraint information in the width and height parameters. 6 * </p> 7 * 8 * <p> 9 * The actual measurement work of a view is performed in 10 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 11 * {@link #onMeasure(int, int)} can and must be overridden by subclasses. 12 * </p> 13 * 14 * 15 * @param widthMeasureSpec Horizontal space requirements as imposed by the 16 * parent 17 * @param heightMeasureSpec Vertical space requirements as imposed by the 18 * parent 19 * 20 * @see #onMeasure(int, int) 21 */ 22 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 23 ...... 24 // measure ourselves, this should set the measured dimension flag back 25 onMeasure(widthMeasureSpec, heightMeasureSpec); 26 ...... 27 }
这里面注释提供了很多信息,这简单翻译并整理一下:
1)该方法被调用,用于找出view应该多大。父布局在witdh和height参数中提供了限制信息;
2)一个view的实际测量工作是在被本方法所调用的onMeasure(int,int)方法中实现的。所以,只有onMeasure(int,int)可以并且必须被子类重写(笔者注:这里应该指的是,ViewGroup的子类必须重写该方法,才能绘制该容器内的子view。如果是自定义一个子控件,extends View,那么并不需要重写该方法);
3)参数widthMeasureSpec:父布局加入的水平空间必要条件;
4)参数heightMeasureSpec:父布局加入的垂直空间必要条件。