问题描述
为了满足功能需求,界面布局中常常需要用到 ScrollView 下嵌套 ListView(GridView) 的情况,ScrollView 可以滚动,而 ListView(GridView) 只作数据展示不能滚动。而写完调试时会发现,ListView(GridView) 只显示了一行数据,自身滚动后能看到剩余数据。原因是ScrollView 中嵌套 ListView(GridView),无法正确的计算ListView(GridView)的高度。
解决方法一
原理:setAdapter后,获取到每一项item的高度,再动态设置listview或者gridview的高度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
public static void setGridViewHeightBasedOnChildren(GridView gridView, int columns) { ListAdapter listAdapter = gridView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; int count = listAdapter.getCount(); View listItem = listAdapter.getView(0, null, gridView); listItem.measure(0, 0); totalHeight = listItem.getMeasuredHeight() + 9;
int yu = count % columns;
ViewGroup.LayoutParams params = gridView.getLayoutParams();
if (yu > 0) { params.height = (count - yu) / columns * (totalHeight + 9) + totalHeight; } else { params.height = count / columns * totalHeight + (count / columns - 1) * 9; }
gridView.setLayoutParams(params); }
public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; int count = listAdapter.getCount(); for (int i = 0; i < count; i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (count - 1)); listView.setLayoutParams(params); }
|
此方法需要注意:
一、是Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法。
二、有时是需要手动把ScrollView滚动至最顶端。
解决方法二
原理:重写 ListView、GridView 的 onMeasure 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class MyListView extends ListView { public MyListView(Context context) { super(context); }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec); }
} - - - - - - - - public class MyGridView extends GridView{ public MyGridView(Context paramContext, AttributeSet paramAttributeSet) { super(paramContext, paramAttributeSet); }
@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
|
修改xml布局文件,代码中不用改动:
1 2 3 4
| <xx..MyGridView(MyListView) xxx xxx </xx..MyGridView(MyListView)>
|
这种方法虽然能够显示完整,但是ListView(GridView)边缘滑动仍会有阴影,如果需要去掉边缘滑动阴影(这些效果耗内存):
1
| android:overScrollMode="never"
|
此方法更详细的理论分析可以参见:
http://blog.csdn.net/aqswde35025/article/details/41863203