Android ScrollView中的ListView只显示一个条目问题
来源:互联网 发布:淘宝视频要求 编辑:程序博客网 时间:2024/05/14 11:04
在ScrollView中放ListView时,ListView默认只显示一个item。
本文将根据这个问题来分析出现这个问题的原因及解决办法。
xml代码如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android:id="@+id/lv" android:layout_width="wrap_content" android:layout_height="wrap_content"> </ListView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="看我干啥,找挨揍啊!"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="没脸啊 还看啊"/> </LinearLayout> </ScrollView></LinearLayout>
Activity中的代码:
private void initView() { ListView listView = (ListView)findViewById(R.id.lv); ArrayList list = new ArrayList(); for(int i=0;i<30;i++){ list.add("item"+i); } ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,list); listView.setAdapter(adapter); }
效果图
那么为什么出现这样的现象呢?
在之前的博客Android UI绘制流程(二)曾经介绍过影响子View大小的因素不只是子View的MeasureSpec,还和父View的MeasureSpec相关。
要分析ListView的大小,首先要从ListView的父View来着手。所以首先来看ViewGroup中的getChildMeasureSpec()方法。
可以看到,在此方法中
public static int getChildMeasureSpec(int spec, int padding, int childDimension) { int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec); int size = Math.max(0, specSize - padding); int resultSize = 0; int resultMode = 0; switch (specMode) { case MeasureSpec.AT_MOST: if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { resultSize = size; resultMode = MeasureSpec.AT_MOST; } else if (childDimension == LayoutParams.WRAP_CONTENT) { resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; } return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }
此方法决定Child的宽和高的MeasureSpec,而决定此MeasureSpec的因素是父View的MeasureSpec和子View的MeasureSpec。
1 子View的MeasureSpec能确定,即ListView中设置的:
android:layout_width="match_parent" android:layout_height="match_parent"
2 而父View的Measurespec怎么确定呢?
同样的道理,父View的MeasureSpec是由父View的父View即ScrollView和父View即LinearLayout本身设定的宽高来共同决定的。所以追本溯源,来看ScrollView中的onMeasure()方法。
@Override 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); }
可以看到其中的这段:
childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec( Math.max(0, MeasureSpec.getSize(parentHeightMeasureSpec) - verticalPadding), MeasureSpec.UNSPECIFIED);
即ScrollView中的每个子布局的高度的SpecMode都是UNSPECIFIED的。即LinearLayout的heightSpecMode==UNSPECIFIED,现在已知LinearLaout的heightSpecMode了,下面再回头来看之前getChildMeasureSpec()中的这段:
case MeasureSpec.UNSPECIFIED: if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) { resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } break;
这段得出结论,当LinearLayout的heightSpecMode==UNSPECIFIED时,无论在 ListView中写match_parent还是wrap_content其实结果都一样,因为决定ListView的heightSpecSize并不是此参数,而是resultSize。而此时ListViewheightSpecMode=UNSPECIFIED。现在ListView的SpecMode已经去定了,我们先不考虑resultSize具体是多少(后面可以发现,其实当ListView中的SpecMode=UNSPECIFIED时,这个值并不能影响ListView的高度),先来看ListView中的onMeasure()方法:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); childHeight = child.getMeasuredHeight(); if (widthMode == MeasureSpec.UNSPECIFIED) { widthSize = mListPadding.left + mListPadding.right + childWidth + getVerticalScrollbarWidth(); } else { widthSize |= (childState & MEASURED_STATE_MASK); } if (heightMode == MeasureSpec.UNSPECIFIED) { heightSize = mListPadding.top + mListPadding.bottom + childHeight + getVerticalFadingEdgeLength() * 2; } setMeasuredDimension(widthSize, heightSize); mWidthMeasureSpec = widthMeasureSpec; }
这段代码不全,我只把需要的截取出来了。根据上面代码中的:
if (heightMode == MeasureSpec.UNSPECIFIED) { heightSize = mListPadding.top + mListPadding.bottom + childHeight + getVerticalFadingEdgeLength() * 2; }
可以得出,当ListVIew的heightMoe==MeasureSpec.UNSPECIFIED时,其高度heightSize的高度为childHeight。至此已经找到了问题的源头。
解决办法:自定义ListView,并在onMeasure方法中修改heightMeasureSpec。这样就可以让ListView默认全部展开。
public class MyListView extends ListView { public MyListView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandedSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandedSpec); }}
再布局中使用自定义控件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.example.practice_click.MyListView android:id="@+id/lv" android:layout_width="wrap_content" android:layout_height="wrap_content"> </com.example.practice_click.MyListView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="看我干啥,找挨揍啊!"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="没脸啊 还看啊"/> </LinearLayout> </ScrollView></LinearLayout>
效果图
- Android ScrollView中的ListView只显示一个条目问题
- 解决ScrollView 中的listView只显示一行的问题:
- android中ScrollView嵌套ListView只显示一条item问题
- android - ScrollView嵌套ListView,ListView自动聚焦到第一个,和只显示一个
- 解决ScrollView嵌套ListView问题 ListView只显示一行问题
- ScrollView内嵌套ListView,ListView只显示一个item
- Android中解决scrollview中嵌套listview的listview只显示一行的问题
- Android---ListView(显示条目)
- Android之将ListView嵌套到ScrollView中只显示一行的问题
- 《Android那些事》——ScrollView嵌套ListView只显示一行的问题的解决方法
- ScrollView中的ListView只显示一条数据的解决方法
- ScrollView嵌套ListView只显示一行的问题
- ScrollView嵌套ListView只显示一行的问题
- 解决ScrollView嵌套ListView只显示一行的问题
- 解决ScrollView中ListView只显示第一条的问题
- ScrollView嵌套ListView只显示一行的问题
- 解决ListView在ScrollView里只显示单行的问题
- ScrollView中嵌套ListView只显示一行问题
- 1548 欧姆诺姆和糖果 51NOD
- tcl安装与学习
- 工业大数据漫谈8:工业大数据的采集
- spark 2.0 metrics example of spark sink -- JmxSink
- 图片圆角实现
- Android ScrollView中的ListView只显示一个条目问题
- alter system flush buffer_cache
- Xamarin XAML语言教程Xamarin.Forms中改变活动指示器颜色
- 动手写一个"liveReload"
- WebApi系列--接口测试工具:WebApiTestClient
- 鼠标拖拽事件
- 目标检测(转载)
- pandas.DataFrame.iterrows
- Spark一千篇旅游日记0002 之 使用idea开发spark程序