面试题-ScrollView嵌套ListView的优化

问题:为什么ScrollView嵌套ListView只显示一条数据

首先看解决方法:自己写一个类继承于ListView并重新测量

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

分析原因首先,ScrollView 肯定会对子View进行测量,看下源码

ScrollView.onMeasure()->Framelayout.onMeasure()->ViewGroup.measureChildWithMargins()给子view调用的->ScrollView.measureChildWithMargins()

 @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 usedTotal = mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin +
                heightUsed;
        //设置子view的设置模式为UNSPECIFIED
        final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                Math.max(0, MeasureSpec.getSize(parentHeightMeasureSpec) - usedTotal),
                MeasureSpec.UNSPECIFIED);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

然后看ListView的onMeasure方法

      //由刚才分析我们可以知道子view这时候走的是这里,所以会显示不全
    if (heightMode == MeasureSpec.UNSPECIFIED) {
            heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                    getVerticalFadingEdgeLength() * 2;
        }
       //所以设置模式为AT_MOST
        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);
        }

        setMeasuredDimension(widthSize, heightSize);

为什么大小设置为(Integer.MAX_VALUE >> 2

答:我们都知道,右边2的两位是模式,后30位是大小Integer.MAX_VALUE 的大小是2的31次方,所以将最大值向右移两位进行赋值。

你可能感兴趣的:(面试题-ScrollView嵌套ListView的优化)