四 View 的测量宽高和最终宽高的区别

本文详细解析了Android中View的测量宽高(getMeasuredHeight())与最终宽高(getHeight())的区别,阐述了两者在不同场景下的表现差异,并通过LinearLayout布局示例说明了其工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

View 的测量宽高和最终宽高有什么区别?

这个问题可以具体为getMeasuredHeight()getHeight()有什么区别。
View

    public final int getHeight() {
        return mBottom - mTop;
    }

再看看 mBottom 、mTop 是怎么来的:
View

    protected boolean setFrame(int left, int top, int right, int bottom) {
           /**
             * 确定子元素的位置
             */
            mLeft = left;
            mTop = top;
            mRight = right;
            mBottom = bottom;
            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
    }

接着看 setFrame 在哪调用的:
View

    public void layout(int l, int t, int r, int b) {
        /**
         *   setFrame设定view的四个顶点的位置,即初始化mLeft、mTop、mBottom、mRight,
         * 四个顶点一旦确定,View在父容器的位置也就确定了
         */
        boolean changed = isLayoutModeOptical(mParent) ?
                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
     }

接着看 layout 在哪调用的,首先肯定是父容器确定子元素位置的时候调用的该方法,由于 layout 是view确定自身的位置,onLayout 是确定子元素的位置,因此应该在父容器的 onLayout 中调用的子元素的 layout,拿 LinearLayout 举例来说:
LinearLayout

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (mOrientation == VERTICAL) {
            layoutVertical(l, t, r, b);
        } else {
            layoutHorizontal(l, t, r, b);
        }
    }

接着看 layoutVertical(l, t, r, b),水平方向和竖直方向的类似。
LinearLayout

    void layoutVertical(int left, int top, int right, int bottom) {
           final int childHeight = child.getMeasuredHeight();
           childTop += lp.topMargin;
           /**
            * 为子元素指定位置
            */
           setChildFrame(child, childLeft, childTop + getLocationOffset(child),childWidth, childHeight);
    }

接着看setChildFrame
LinearLayout

    private void setChildFrame(View child, int left, int top, int width, int height) {
        child.layout(left, top, left + width, top + height);
    }

终于在 onlayout 中找到了child.layout方法,重新屡一下:
则在 View 中getHeight方法中的mBottom - mTop是等于 LinearLayout 中setChildFrame的参数 height,接着查看layoutVertical方法中的 childHeight 的来源:child.getMeasuredHeight(),即测量宽高。
默认情况下是上面这种情况,getMeasuredHeight()getHeight()是相等的。但是如果重写 View 的layout(),那么在 LinearLayout 调用setChildFrame的时候就会调用重写的 View 的layout()

    public void layout(int l, int t, int r, int b) {
        super.layout(l, t, r+100, b+100);
    }

如果按照上面这样重写,那么getHeight()得到的值会比getMeasuredHeight()大100。
注意:在某些情况下,View 需要多次 measure 才能确定自己的测量宽高,再前几次的测量过程中,得出的测量宽高有可能和最终宽高不一致,但是到了最后,测量宽高和最终宽高还是相同的,除非有意重写 layout() 修改。
注意
虽说在 Layout 阶段确定 View 的最终宽高,但是在 onLayout 中调用子 view 的getWidth()经常取不到宽高值,除非子 View 的位置已经确定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值