ScrollView嵌套Listview只显示一行的解决方案

当ScrollView内嵌套ListView时,可能只会显示ListView的第一行。原因是ScrollView在测量时将模式设为了UNSPECIFIED,导致ListView仅测量一行。解决办法包括自定义ListView重写onMeasure方法或在XML中设置ScrollView的fillViewport属性为"true",使ListView高度适应ScrollView。
摘要由CSDN通过智能技术生成

问题:

ScrollView里面嵌套Listview,ListView为什么只显示第一行的高度?

解析源码:
在listview的onMeasure方法中可以看到,当测量模式为UNSPECIFIED的时候只测量一行的高度,测量模式为AT_MOST的时候才是测量整个listview的高度

if (heightMode == MeasureSpec.UNSPECIFIED) {
    heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                    getVerticalFadingEdgeLength() * 2;
}

if (heightMode == MeasureSpec.AT_MOST) {
    // TODO: after first layout we should maybe start at the first visible position, not 0
    heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1);
}

所以我们就可以猜想,是不是listview的父容器Scrollview传给listview的测量模式是UNSPECIFIED呢?

经过在Scrollview源码中一番查找,我们可以找到Scrollvie重写了measureChildWithMargins方法,并给子view设置了测量模式

@Override
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 = MeasureSpec.makeSafeMeasureSpec(
            MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED);

    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}

解决方法:

1、自定义listview,重写onMeasure方法

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2 ,MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightSpec);
}

2、在Scrollview的onMeasure方法中,mFillViewport的默认值是false,直接return了,没法设置child的高度,所以可以在xml中设置android:fillViewport=”true”,把listview的高度设置成Scrollview的高度减去padding

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值