博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ScrollView ListView 嵌套问题
阅读量:5841 次
发布时间:2019-06-18

本文共 4424 字,大约阅读时间需要 14 分钟。

ScrollView 嵌套ListView 出现不兼容问题,有下面这种解决方案

自定义ListView 继承ListView 重写 onMeasure方法

public class MyListView extends ListView {    public MyListView(Context context) {        super(context);    }    public MyListView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST) ;        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }}复制代码

这里要讲的是为什么要设置MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST)

下面看Scrollview 测量子视图的方法

protected void measureChild(View child, int parentWidthMeasureSpec,        int parentHeightMeasureSpec) {    ViewGroup.LayoutParams lp = child.getLayoutParams();    int childWidthMeasureSpec;    int childHeightMeasureSpec;    childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft            + mPaddingRight, lp.width);    final int verticalPadding = mPaddingTop + mPaddingBottom;    childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(            Math.max(0, MeasureSpec.getSize(parentHeightMeasureSpec) - verticalPadding),            MeasureSpec.UNSPECIFIED);    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);}复制代码

给子视图的heightMeasureSpec 设置了 UNSPECIFIED 参数

下面再看下ListView的测量

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    // Sets up mListPadding    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    ...    if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED            || heightMode == MeasureSpec.UNSPECIFIED)) {        final View child = obtainView(0, mIsScrap);        ...        childWidth = child.getMeasuredWidth();        childHeight = child.getMeasuredHeight();         ...    }     if (heightMode == MeasureSpec.UNSPECIFIED) {        //相当于 一个子item的高度 + padding + VerticalFadingEdgeLength() * 2        //这样导致listView 显示只有差不多 一个item高度        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);    }    setMeasuredDimension(widthSize, heightSize);    mWidthMeasureSpec = widthMeasureSpec;}复制代码

看了上面的几处源码大家应该理解了ScrollView 嵌套ListView 布局的问题了吧

那我们设置的时候为什么要 Integer.MAX_VALUE>>2 右移两位呢?

widthMeasureSpec heightMeasureSpec : 会包含两个信息是一个32位的值,第一个信息是模式:2位 值:30位  

那为什么要使用Integer.MAX_VALUE

看ListView 测量子视图的高度

final int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition,        int maxHeight, int disallowPartialChildPosition) {     for (i = startPosition; i <= endPosition; ++i) {        child = obtainView(i, isScrap);        measureScrapChild(child, i, widthMeasureSpec, maxHeight);        if (i > 0) {            // Count the divider for all but one child            returnedHeight += dividerHeight;        }        // Recycle the view before we possibly return from the method        if (recyle && recycleBin.shouldRecycleViewType(                ((LayoutParams) child.getLayoutParams()).viewType)) {            recycleBin.addScrapView(child, -1);        }        returnedHeight += child.getMeasuredHeight();                  if (returnedHeight >= maxHeight) { //Integer.MAX_VALUE 防止进入这个if判断            return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1)                        && (i > disallowPartialChildPosition) // We've past the min pos                        && (prevHeightWithoutPartialChild > 0) // We have a prev height                        && (returnedHeight != maxHeight) // i'th child did not fit completely                    ? prevHeightWithoutPartialChild                    : maxHeight;        }        if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) {            prevHeightWithoutPartialChild = returnedHeight;        }    }    // At this point, we went through the range of children, and they each    // completely fit, so return the returnedHeight    return returnedHeight;}复制代码

看了这些,大家应该明白为什么这么做了吧

转载于:https://juejin.im/post/5c0e6c5f51882530544f2635

你可能感兴趣的文章
Jquery Form表单取值
查看>>
Android API level 与version对应关系
查看>>
Team Name
查看>>
String类
查看>>
西门子_TDC_数据耦合小经验
查看>>
[LeetCode] Copy List with Random Pointer
查看>>
openstack部署之nova
查看>>
JS组件系列——表格组件神器:bootstrap table
查看>>
存储过程Oracle(一)
查看>>
log4j日志归档
查看>>
mysql遇见error,1049
查看>>
codevs——2822 爱在心中
查看>>
Python基础班---第一部分(基础)---Python基础知识---认识Python
查看>>
JAVA MAC 配置
查看>>
1134 最长上升子序列 (序列型 DP)
查看>>
js冒泡排序
查看>>
第一次作业 4班卢炳武
查看>>
抽象类的调用
查看>>
使用硬盘,安装双系统,Win7+CentOS
查看>>
Javascript学习总结
查看>>