measure

四、视图的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:父布局加入的垂直空间必要条件。

猜你喜欢

转载自www.cnblogs.com/andy-songwei/p/10888735.html