自定义View之onMeasure开幕——测量模式

其实onMeasure()测量模式难明白是,你没有看源码我们可以看看ViewGroup是如何处理的
首先是测量模式

  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);
    }


看一下代码测量的规则就很好懂了 ,测量模式是父控件和子控件一起决定的。

大家看看这个图片


image.png

测量的模式可以为以下三种:

1、EXACTLY
精确值模式,当我们将控件的layout width 属性或layout height 属性指定为具体数值时,
比如andorid:layout_ width="100dp", 或者指定为match_ parent 属性时(占据父View的大小),系统使用的是EXACTLY模式。

效果:父View决定自元素的确切大小,子View将被限定在给定的边界里而忽略它本身大小;

2、AT MOST
最大值模式,当控件的layout_ width 属性或layout_ height 属性指定为wrap_ content 时,
控件大小一一般随着控件的子控件或内容的变化而变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可。

效果:子View至多达到指定大小的值

3、UNSPECIFIED
自由模式, 不指定其大小测量模式,View想多大就多大。

效果:父View不给子View施加任何束缚,子View可以得到任意想要的大小

View类默认的onMeasure方法只支持EXACTLY模式,所以如果在自定义控件的时候不重写onMeasure方法的话,就只能使用EXACTLY模式。控件可以响应你指定的具体宽高值或者是match_ parent 属性。而如果要让自定义View支持wrap_ content 属性,那么就必须重写onMeasure()方法来指定wrap_ content 时的大小。

总结:想要子View得到测量模式,你要看看父VIew的测量模式的束缚规则,在规则之下你在去决定你的测量模式

部分引用:
1、有心课堂
2、Android群英传

你可能感兴趣的:(自定义View之onMeasure开幕——测量模式)