您的位置:首页 > 其它

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

2017-05-09 22:54 489 查看
(1)查看ListView的测量方法,关注垂直方向高度

会发现当其mode为 MeasureSpec.UNSPECIFIED时

...

final
View child =
obtainView(0, mIsScrap);

...

childHeight = child.getMeasuredHeight();

...

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

}

obtainView在AbsListView里面,表示拿对应位置的item,obtainView(0, mIsScrap)表示第一item,也就是在heightMode == MeasureSpec.UNSPECIFIED时,只测量一行的高度;而在AT_MOST时候,他会测量所有item的高度。

(2)由于子View的测量模式,是父容器传递进来的,这时候查看ScrollView的传递的测量模式查看ScrollView的onMeasure方法

@Override

protected void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);

...

它会先调用父类的onMeasure方法,而父类的onMeasure会调用measureChildWithMargins,这时会发现ScrollView重写了measureChildWithMargins方法

(3)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);
}
可以看到,其默认设置的Mode为MeasureSpec.UNSPECIFIED的;
这就是为什么ScrollVIew嵌套ListView只显示一行的原因

(4)解决办法:

自定义ListView ,重写其onMeasure方法,修改其mode,将其重新设置为AT_MOST:

//Interger.Max_VALUE>>2 ,高两位是设置mode,后30位的才是高度

int heightSpec = MeasureSpec.makeMeasureSpec(Interger.Max_VALUE>>2,MeasureSpec。AT_MOST);

super.onMeasure(widhtspec,heightSpec);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐