在我们日常开发中,我们可能会碰到这样的情形:在某个内容很多的页面中用listview显示几条数据,或者用gridview显示几张图片,由于页面内容很多,一般都要在最外层加上SrcollView来显示全部数据, 那么问题来了:
listview,gridview本身就是支持滑动的组件,而嵌套在可滑动的scrollview中会就发生冲突,最终出现的结果可能就是:listview,gridview只显示一行,除非我们给他们指定高度,否高度设置为match_parent或者wrap_content时系统是无法计算出其的真实高度的,因此我们需要根据我们listview或者gridview中的具体数据来动态计算其高度!
在listview中:
我们只需要获得该listview有多少个item 以及每个item的高度和listview分割线的高度即可:
/** scrollView中动态获得listview高度,并全部显示listview */
public void setListViewHeight(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0, len = listAdapter.getCount(); i < len; i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);// 计算子项目view的高度
totalHeight += listItem.getMeasuredHeight();// 统计所有子项目的高度
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight // listView.getDividerHeight()获取子项间分隔线占用的高度
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
在gridview中,我们就需要知道其横向有多少行,如果设置了行间距,我们还要获得该行间距,在android4.1(api16)以上的版本中,gridview提供了获取这两个属性的方法:
GridView.getNumColumns(),GrivdView.getVerticalSpacing();
那么方法如下:
private void setGridViewHeight(GridView gridView) {
ListAdapter adapter = gridView.getAdapter();
if (adapter == null) {
return;
}
int totalHeigt = 0;
double itemCount = adapter.getCount();
double horizentalNumger = gridView.getNumColumns();
int verticalNumber = (int) Math.ceil(itemCount / horizentalNumger);
View item = adapter.getView(0, null, gridView);
item.measure(0, 0);
int itemHeight = item.getMeasuredHeight();
int space = gridView.getVerticalSpacing();
totalHeigt = verticalNumber * itemHeight + (verticalNumber - 1) * space;
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeigt;
gridView.setLayoutParams(params);
}
如果是在4.1一下的版本中,我们可以将指定在布局文件中的numColumns和verticalsapcing作为方法的参数:
<GridView
android:id="@+id/gv_floor_images"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:horizontalSpacing="5dp"
android:listSelector="@color/transparent"
android:numColumns="3"
android:verticalSpacing="5dp"
tools:ignore="NestedScrolling" >
</GridView>
方法如下:
private void setGridViewHeight(GridView gridView, int numColums, int space) {
ListAdapter adapter = gridView.getAdapter();
if (adapter == null) {
return;
}
int totalHeigt = 0;
double itemCount = adapter.getCount();
double horizentalNumger = numColums;
// double horizentalNumger = gridView.getNumColumns();API 11以下无此方法
int verticalNumber = (int) Math.ceil(itemCount / horizentalNumger);
View item = adapter.getView(0, null, gridView);
item.measure(0, 0);
int itemHeight = item.getMeasuredHeight();
// int space = gridView.getVerticalSpacing();API 16以下无此方法
totalHeigt = verticalNumber * itemHeight + (verticalNumber - 1) * space;
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeigt;
gridView.setLayoutParams(params);
}
另一种思路就是,我们自定义一个MyGridview继承自GridView,在其中添加获取这两个值的方法,然后再使用第一种设置方法也可以。
总结:实际开发中,这种冲突的嵌套方式是不推荐的,当实在要使用时,可以采用上述方法解决问题。