MeasureSpec总结

作者: MryU93 | 来源:发表于2016-11-28 14:27 被阅读142次

    MeasureSpec

    View的LayoutParams根据父容器所施加的规则转换成对应的MeasureSpec,然后根据这个MeasureSpec来测量出View的宽高。MeasureSpec代表一个32位int值,高2位代表SpecMode(测量模式),低30位代表SpecSize(在某个测量模式下的规格大小)

    //获取SpecSize:
    int specSize = MeasureSpec.getSize(measureSpec)
    //获取specMode
    int measureSpec=MeasureSpec.makeMeasureSpec(size, mode);
    

    SpecMode一共有三种:

    1. UNSPECIFIED :父容器不对View进行任何限制,要多大给多大,一般用于系统内部

    2. EXACTLY:父容器检测到View所需要的精确大小,这时候View的最终大小就是SpecSize所指定的值,对应LayoutParams中的match_parent和具体数值这两种模式

    3. AT_MOST :对应View的默认大小,不同View实现不同,View的大小不能大于父容器的SpecSize,对应LayoutParams中的wrap_content

    MeasureSpec和LayoutParams的对应关系

    View的MeasureSpec由父容器的MeasureSpec和自身的LayoutParams共同决定。

    对于普通View来说,View的measure过程由ViewGroup传递过来,measureChildWithMargins源码

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

    measureChildWithMargins()方法对子元素进行measure,在调用子元素的measure方法之前先通过
    measureChildWithMargins()方法得到子元素的MeasureSpec,子元素的MeasureSpec与父容器的MeasureSpec和自身的LayoutParams有关,还与view的margin和padding有关。

    View 的MeasureSpec创建规则(getChildMeasureSpec方法的表格呈现)

    • 当View采用固定宽/高时(即设置固定的dp/px),不管父容器的MeasureSpec是什么,View的MeasureSpec都是EXACTLY模式,并且大小遵循我们设置的值。
    • 当View的宽/高是match_parents时,如果父容器的模式是精准模式,那么View也是精准模式并且其大小是父容器的剩余空间;如果父容器是最大模式那么View也是最大模式并且其大小不会超过父容器的剩余空间
    • 当View的宽/高是wrap_content时,View的MeasureSpec都是AT_MOST模式并且其大小不能超过父容器的剩余空间。

    只要提供父容器的MeasureSpec和子元素的LayoutParams,就可以确定出子元素的MeasureSpec,进一步便可以确定出测量后的大小。

    相关文章

      网友评论

      • 微弱的倾诉者:
        谢谢分享,文章写得真不错。。。下面的这个好像是保存信息的吧
        //获取specMode
        int measureSpec=MeasureSpec.makeMeasureSpec(size, mode);

      本文标题:MeasureSpec总结

      本文链接:https://www.haomeiwen.com/subject/azjopttx.html