在之前的编程里,我还没有遇到过要在一个ListView中嵌套一个GridView或是在一个GridView中嵌套一个ListView。所以今天事儿来了!我花了一将近3个小时,找到了为什么我在一个ListView中添加一个GridView时,只显示一行GridView的原因;另外,这3个小时的付出,又让我学会了另一件事——在局部找不到原因的时候,要跳出来,从更大的范围寻找原因。废话了这么多,那么究竟是为什么只显示一行GridView呢?
因为在Android中,有这样一个限制,两ScrollView型的控件不能相互嵌套。像ListView和GridView就都是ScrollView型的控件。因为嵌套后,两个ScrollView型控件的滑动效果就丧失了,同时被嵌套控件的高度也被限定为一行的高度。那我们还能不能嵌套两个ScrollView型的控件呢?肯定是可以的。方法有两种:一是我们去需要自定义ListView或是GridView,并重写其onMeasure()方法。如下:
- public class NoScrollGridView extends GridView {
- public NoScrollGridView(Context context) {
- super(context);
- }
- public NoScrollGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);
- super.onMeasure(widthMeasureSpec, expandSpec);
- }
- }
ListView也同理。
还有一种方法是我们重新动态地计算我们现在需要的高度。在我们调用Adapter的时候,我们获得现在这个时候的GridView有多少个,单个GridView的高度,然后计算总高度。具体代码如下:
-
-
-
-
- public static void setListViewHeightBasedOnChildren(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);
- totalHeight += listItem.getMeasuredHeight();
- }
-
- ViewGroup.LayoutParams params = listView.getLayoutParams();
- params.height = totalHeight
- + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
-
-
- listView.setLayoutParams(params);
- }
在我们setAdapter()的之前,我们调用上面的方法,如setListViewHeightBasedOnChildren(accomplishmentStateListView);
因为我是在ListView中嵌套GridView,所以重新计算GridView的总高度的时候,要放在setAdapter(...GridViewAdapter)这个BaseAdapter的衍生类里。代码如下:
-
-
-
-
- public static void setGridViewHeightBasedOnChildren(GridView gridView) {
-
- ListAdapter listAdapter = gridView.getAdapter();
- if (listAdapter == null) {
- return;
- }
- int rows;
- int columns = 0;
- int horizontalBorderHeight = 0;
- Class<?> clazz = gridView.getClass();
- try {
-
- Field column = clazz.getDeclaredField("mRequestedNumColumns");
- column.setAccessible(true);
- columns = (Integer) column.get(gridView);
-
- Field horizontalSpacing = clazz
- .getDeclaredField("mRequestedHorizontalSpacing");
- horizontalSpacing.setAccessible(true);
- horizontalBorderHeight = (Integer) horizontalSpacing.get(gridView);
- } catch (Exception e) {
-
- e.printStackTrace();
- }
-
- if (listAdapter.getCount() % columns > 0) {
- rows = listAdapter.getCount() / columns + 1;
- } else {
- rows = listAdapter.getCount() / columns;
- }
- int totalHeight = 0;
- for (int i = 0; i < rows; i++) {
- View listItem = listAdapter.getView(i, null, gridView);
- listItem.measure(0, 0);
- totalHeight += listItem.getMeasuredHeight();
- }
- ViewGroup.LayoutParams params = gridView.getLayoutParams();
- params.height = totalHeight + horizontalBorderHeight * (rows - 1);
- gridView.setLayoutParams(params);
- }
这样我们就可以在ListView中添加GridView了。。。
注:两个SrcollView型的控件可以是:
<ListView, GridView>;
<GridView,ListView>;
<ListView,ListView>;
<GridView, GridView>;
<ListView, ScrollView>;
<ScrollView,ListView>;
<GridView, ScrollView>;
<ScrollView, GridView>;
<ScrollView, ScrollView>;
... ...