美文网首页
普通View的MeasureSpec的创建规则

普通View的MeasureSpec的创建规则

作者: 雨来 | 来源:发表于2021-09-30 16:00 被阅读0次

    可以先读的文章:
    https://cloud.tencent.com/developer/article/1459335

    我先借用两张图:

    1、

    image.png

    2、

    image.png

    上面两张图的由来:(前面几个判断我是加了注释了)

    public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
    
            //spc 传的是(自己onMeasure方法接收到 widthMeausreSpec 和 heightMeasureSpec) 这个方法是自己测量子view的时候用的
    
            //padding  这个参数则自己的 getPaddingLeft()和getPaddingRight()  childDimension 也是子view的 layoutParmars.width 或 layoutParmars.height
    
            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) {
    
                        //如果 自己的mode是 exactly 并且 子View的尺寸是一个确定的值 也就是exactly 那么 子view的尺寸就是自己的 childDimension (也就像 一个线性布局 设置固定高度为 100个dp 里面再有一个TextView高度设置成
                        // 固定高度为 30dp 那么这个 TextView的高度就是 30个dp)
                        resultSize = childDimension;
    
                        //如果 自己的mode 是exactly 并且子view的 尺寸是一个具体的值并且大于0 那么 子view的 mode 就是  MeasureSpec.EXACTLY     resultMode = MeasureSpec.EXACTLY;
                        resultMode = MeasureSpec.EXACTLY;
                    } else if (childDimension == LayoutParams.MATCH_PARENT) {
                        //子view的的 尺寸  如果 父mode 是exactly(确切的值 如 100dp ) 那么子view的 尺寸LayoutParams.MATCH_PARENT 那么 子view的尺寸就是 size 子view的尺寸是父view给自己的自己的参考尺寸
                        // Child wants to be our size. So be it. (孩子想成为我们的尺寸 那么给它 自己有多大就给子view多大)
                        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 = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                        resultMode = MeasureSpec.UNSPECIFIED;
                    } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                        // Child wants to determine its own size.... find out how
                        // big it should be
                        resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                        resultMode = MeasureSpec.UNSPECIFIED;
                    }
                    break;
            }
            //noinspection ResourceType
            return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
        }
    

    通过上面的方法 我们应该明天上面两张图怎么看了
    这三种模式(mode)是通过 父view给我们 也就是自身的mode


    image.png

    通过方法然后再看图的总结是(如何看图):
    如果子view是固定大小具体数值 dp/px的话,如果自身的mode是 exactly 那么 那么子view 的mode和size就是下面标红的


    image.png

    这个图一定要学会看如果这个图都看不懂,更不要提说自己会自定义view了

    最后的总结:

    一个view的measureSpc 是由自身的layoutParams和父layout的measureSpec决定的

    父layout的 measureSpec 是如何获取的呢
    image.png

    当前View获取父layout的measureSpec 只需要在当前View onMeasure() 方法里拿到 widthMeasureSpec
    然后通过api MeasureSpec.getMode(widthMeasureSpec) 就可以获取了

    非常不错的一篇博文:
    https://www.jianshu.com/p/3b6d0c17cdb0

    相关文章

      网友评论

          本文标题:普通View的MeasureSpec的创建规则

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