理解MeasureSpec

来源:互联网 发布:cdn 开源软件 编辑:程序博客网 时间:2024/05/21 12:16

理解MeasureSpec

以下的内容参考《Android 开发艺术探讨》

MeasureSpec在很大的程度上决定了一个view的尺寸规格。在测量过程中,系统会将View的Layoutparams 根据父容器所施加的规则转换成对应的MeasureSpec,然后在根据这个Measure来测量出View的宽高。

  • MeasureSpec 和 LayoutParams的对应关系

    在View测量的时候,系统会将LayoutParams在父窗体的约束下转换成对应的MeasureSpec,然后在根据这个MeasureSpec来确定View测量的后的宽高。

  • DecorView
    其MeasureSpec由窗口和自身的LayoutParams来共同决定
    desiredWindowWidth 和 disiredWindowHeight 是屏幕的尺寸:

    这里写图片描述

    这里写图片描述

  • 普通View
    其MeasureSpec由父容器的MeasureSpec和自身的LayoutParams来共同决定

protected void measureChildWithMargins(View child,            int parentWidthMeasureSpec, int widthUsed,            int parentHeightMeasureSpec, int heightUsed) {        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,                mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin                        + widthUsed, lp.width);        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,                mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin                        + heightUsed, lp.height);        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);    }
对于普通View来说,View 的measure过程由ViewGroup传递而来,在调用子元素的measure方法之前会先通过getChildMeasureSpec方法来得到子元素的MeasureSpec.具体情况可以看下ViewGroup的getChildMeasureSpec方法
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {        int specMode = MeasureSpec.getMode(spec);        int specSize = MeasureSpec.getSize(spec);        int size = Math.max(0, specSize - padding);        int resultSize = 0;        int resultMode = 0;        switch (specMode) {        // Parent has imposed an exact size on us        case MeasureSpec.EXACTLY:            if (childDimension >= 0) {                resultSize = childDimension;                resultMode = MeasureSpec.EXACTLY;            } else if (childDimension == LayoutParams.MATCH_PARENT) {                // Child wants to be our size. So be it.                resultSize = size;                resultMode = MeasureSpec.EXACTLY;            } else if (childDimension == LayoutParams.WRAP_CONTENT) {                // Child wants to determine its own size. It can't be                // bigger than us.                resultSize = size;                resultMode = MeasureSpec.AT_MOST;            }            break;        // Parent has imposed a maximum size on us        case MeasureSpec.AT_MOST:            if (childDimension >= 0) {                // Child wants a specific size... so be it                resultSize = childDimension;                resultMode = MeasureSpec.EXACTLY;            } else if (childDimension == LayoutParams.MATCH_PARENT) {                // Child wants to be our size, but our size is not fixed.                // Constrain child to not be bigger than us.                resultSize = size;                resultMode = MeasureSpec.AT_MOST;            } else if (childDimension == LayoutParams.WRAP_CONTENT) {                // Child wants to determine its own size. It can't be                // bigger than us.                resultSize = size;                resultMode = MeasureSpec.AT_MOST;            }            break;        // Parent asked to see how big we want to be        case MeasureSpec.UNSPECIFIED:            if (childDimension >= 0) {                // Child wants a specific size... let him have it                resultSize = childDimension;                resultMode = MeasureSpec.EXACTLY;            } else if (childDimension == LayoutParams.MATCH_PARENT) {                // Child wants to be our size... find out how big it should                // be                resultSize = 0;                resultMode = MeasureSpec.UNSPECIFIED;            } else if (childDimension == LayoutParams.WRAP_CONTENT) {                // Child wants to determine its own size.... find out how                // big it should be                resultSize = 0;                resultMode = MeasureSpec.UNSPECIFIED;            }            break;        }        return MeasureSpec.makeMeasureSpec(resultSize, resultMode);    }

对于getChildeMeasureSpec的工作原理进行了梳理

这里写图片描述

0 0