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);
会发现当其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);
相关文章推荐
- ScrollView嵌套listview、gradview等 嵌套式高度显示问题的解决办法
- ScrollView中嵌套ListView时,listview高度显示的问题
- ScrollView嵌套ListView,gridView只显示一行解决方案 (以及计算显示高度错误问题)
- scrollview同时嵌套listview和gridview 显示高度问题【只显示一行】
- ScrollView中嵌套ListView造成ListView高度只显示一行解决办法
- 解决ScrollView嵌套ListView,列表项高度不同,显示不全的问题
- 【Android基础学习】动态设置 listView的高度,解决scrollView中嵌套listview时显示不全的问题
- ListView(ScrollView)嵌套ListView、GridView显示不全,内容大于一行计算的高度不正确的解决办法
- ScrollView中嵌套ListView让ListView显示完整高度
- 解决GridView,ListView嵌套在ScrollView时只显示一行高度的问题
- 解决scrollview嵌套listview ,listview异常,数据不显示,高度异常,布局异常
- ScrollView中嵌套ListView,TextView只显示一行的高度解决方案
- 解决GridView,ListView嵌套在ScrollView时只显示一行高度的问题
- 在ScrollView中嵌套ListView时,ListView只能显示一行多一点
- ListView或GridView与ScrollView共存,高度显示问题
- ScrollView中嵌套ListView时显示不全的解决方案
- ScrollView中嵌套GridView,Listview不显示全部item的问题
- android 关于 ScrollView嵌套GridView,ListView 显示和滑动的问题
- android 关于 ScrollView嵌套GridView,ListView 显示和滑动的问题
- android ScrollView中嵌套GridView,ListView只显示一行的解决办法