android listview scrollview,AndroidScrollView嵌套ListView无法全部显示全部问题

嘿,今天的你过的还好吗,今天分享解决ScrollView嵌套ListView无法全部显示问题的经历

首先我们看一下ScrollView源码,发现他继承了FrameLayout,而FrameLayout下的onMeasure方法有如下代码

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int count = getChildCount();

//拿到它的子View然后循环去测量

for (int i = 0; i < count; i++) {

final View child = getChildAt(i);

if (mMeasureAllChildren || child.getVisibility() != GONE) {

//调用父类的方法进行测量,重要方法因为Scrollview重写了这个方法所以出现的问题

measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);

final LayoutParams lp = (LayoutParams) child.getLayoutParams();

maxWidth = Math.max(maxWidth,

child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);

maxHeight = Math.max(maxHeight,

child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);

childState = combineMeasuredStates(childState, child.getMeasuredState());

if (measureMatchParentChildren) {

if (lp.width == LayoutParams.MATCH_PARENT ||

lp.height == LayoutParams.MATCH_PARENT) {

mMatchParentChildren.add(child);

}

}

}

}

}

很明显,就是循环查找自己的子View不是GONE的话就调用ViewGroup的measureChildWithMargins方法

发现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;

final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(

Math.max(0, MeasureSpec.getSize(parentHeightMeasureSpec) - usedTotal),

MeasureSpec.UNSPECIFIED);

child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

}

代码里ScrollView重写了measureChildWithMargins方法对他的childHeightMeasureSpec进行了设置.设置他的高度的测量模式heightMode为MeasureSpec.UNSPECIFIED.然后调用child.measure(childWidthMeasureSpec,childHeightMeasureSpec);方法

接下来我们在看看ListView的源码

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// Sets up mListPadding

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//获得高度的模式

final int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

int childHeight = 0

//如果item数量大于0并且有个模式为--UNSPECIFIED执行此方法

if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED

|| heightMode == MeasureSpec.UNSPECIFIED)) {

final View child = obtainView(0, mIsScrap);

childHeight = child.getMeasuredHeight();

//如果高度的模式为UNSPECIFIED执行,我们通过刚刚查看ScrollView的源码发现是这种模式所以此方法为true

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);

}

setMeasuredDimension(widthSize, heightSize);

}

这样可以清楚看出第一个判断是如果Item的总数大于0并且它的高或者宽有一个模式为MeasureSpec.UNSPECIFIED就会执行这个方法,正常情况下这个判断应该 为true.就是拿到它的一个item的高度childHeight = child.getMeasuredHeight();紧接着它判断它的高度的模式是否为MeasureSpec.UNSPECIFIED显然也是true所以他就是让它的整个的高度等于childHeight 最后完成setMeasuredDimension(widthSize,heightSize)

那就可以知道出现这个原因是在scrollView中ListView在OnMeasure阶段无法测出实际的高度,我们需要给他设置AT_MOST模式以支持很大的高度。这时候可以自定义一个MyListView 继承自Listview,然后重写onMeasure方法即可:

接下来是我的解决办法

1.创建一个MyListView让他继承ListView

2.重写onMeasure方法

3.调用MyListView

代码实现方法首先是MyListView

public class MyListView extends ListView {

public MyListView(android.content.Context context, android.util.AttributeSet attrs) {

super(context, attrs);

}

/**

* 设置不滚动

* 重写onMeasure方法

*/

public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,

MeasureSpec.AT_MOST);

super.onMeasure(widthMeasureSpec, expandSpec);

}

}

最后调用MyListView

android:id="@+id/list_lv"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

测试后结果ok,解决问题

没更新动态或者频繁更新动态的时候都是在认真生活

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值