Android自定义ViewGroup遇到的问题

本文探讨了在Android自定义ViewGroup时遇到的问题,主要集中在onMeasure()方法中测量子View的问题。当使用不当的测量规格时,无论子View的layoutParams设置为match_parent还是wrap_content,其实际表现总是自适应内容宽度。通过深入研究getChildMeasureSpec()方法,可以理解并解决这个问题。
摘要由CSDN通过智能技术生成
  • 问题一
    说明:自定义了一个ViewGroup,在onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法中去测量子view的时候使用的是:

    measureChildren(MeasureSpec.makeMeasureSpec(sizeWidth, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(sizeHeight, MeasureSpec.UNSPECIFIED));
    

    导致添加的view的时候无聊view的layoutParams是match_parent还是wrap_content,显示的时候都是自适应内容宽度的,即使在match_parent的时候看layoutParams的确是match_parent.
    所以还是仔细研究了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) {
        // 当父布局的mode为EXACTLY的时候
        // Parent has imposed an exact size on us
        case MeasureSpec.EXACTLY:
            if (childDimension >= 0) {
               //如果子view设置了具体的数值,则子view就具有具体的数值
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size. So be it.
                //如果子view设置了的layoutParams为match_parent,则子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.
                //如果子view设置了的layoutParams为warp_content,则子view就自适应内容大小,但最大具有父布局的数值
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            }
            break;
        // Parent has imposed a maximum size on us
        // 当父布局的mode为AT_MOST的时候
        case MeasureSpec.AT_MOST:
            if (childDimension >= 0) {
                // Child wants a specific size... so be it
                //如果子view设置了具体的数值,则子view就具有具体的数值
                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.
                //如果子view设置了的layoutParams为match_parent,则子view就自适应内容大小,但最大具有父布局的数值
                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.
                //如果子view设置了的layoutParams为warp_content,则子view就自适应内容大小,但最大具有父布局的数值
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            }
            break;
        // Parent asked to see how big we want to be
        // 当父布局的mode为UNSPECIFIED的时候
        case MeasureSpec.UNSPECIFIED:
            if (childDimension >= 0) {
                // Child wants a specific size... let him have it
                //如果子view设置了具体的数值,则子view就具有具体的数值
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size... find out how big it should  be
                //如果子view设置了的layoutParams为match_parent,则子view就自适应内容大小
                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
                //如果子view设置了的layoutParams为warp_content,则子view就自适应内容大小
                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                resultMode = MeasureSpec.UNSPECIFIED;
            }
            break;
        }
        //noinspection ResourceType
        return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值