两个srcollView

在之前的编程里,我还没有遇到过要在一个ListView中嵌套一个GridView或是在一个GridView中嵌套一个ListView。所以今天事儿来了!我花了一将近3个小时,找到了为什么我在一个ListView中添加一个GridView时,只显示一行GridView的原因;另外,这3个小时的付出,又让我学会了另一件事——在局部找不到原因的时候,要跳出来,从更大的范围寻找原因。废话了这么多,那么究竟是为什么只显示一行GridView呢?

        因为在Android中,有这样一个限制,两ScrollView型的控件不能相互嵌套。像ListView和GridView就都是ScrollView型的控件。因为嵌套后,两个ScrollView型控件的滑动效果就丧失了,同时被嵌套控件的高度也被限定为一行的高度。那我们还能不能嵌套两个ScrollView型的控件呢?肯定是可以的。方法有两种:一是我们去需要自定义ListView或是GridView,并重写其onMeasure()方法。如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public class NoScrollGridView extends GridView {   
  2.     public NoScrollGridView(Context context) {   
  3.         super(context);   
  4.     }   
  5.     public NoScrollGridView(Context context, AttributeSet attrs) {   
  6.         super(context, attrs);   
  7.     }  
  8.   
  9.     @Override   
  10.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   
  11.         int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);   
  12.         super.onMeasure(widthMeasureSpec, expandSpec);   
  13.     }  
  14. }  
ListView也同理。

还有一种方法是我们重新动态地计算我们现在需要的高度。在我们调用Adapter的时候,我们获得现在这个时候的GridView有多少个,单个GridView的高度,然后计算总高度。具体代码如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 重新计算listView高度 
  3.      * @param listView 
  4.      */  
  5.     public static void setListViewHeightBasedOnChildren(ListView listView) {  
  6.         // 获取ListView对应的Adapter  
  7.         ListAdapter listAdapter = listView.getAdapter();  
  8.         if (listAdapter == null) {  
  9.             return;  
  10.         }  
  11.   
  12.         int totalHeight = 0;  
  13.         for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目  
  14.             View listItem = listAdapter.getView(i, null, listView);  
  15.             listItem.measure(00); // 计算子项View 的宽高  
  16.             totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度  
  17.         }  
  18.   
  19.         ViewGroup.LayoutParams params = listView.getLayoutParams();  
  20.         params.height = totalHeight  
  21.                 + (listView.getDividerHeight() * (listAdapter.getCount() - 1));  
  22.         // listView.getDividerHeight()获取子项间分隔符占用的高度  
  23.         // params.height最后得到整个ListView完整显示需要的高度  
  24.         listView.setLayoutParams(params);  
  25.     }  
在我们setAdapter()的之前,我们调用上面的方法,如setListViewHeightBasedOnChildren(accomplishmentStateListView);

因为我是在ListView中嵌套GridView,所以重新计算GridView的总高度的时候,要放在setAdapter(...GridViewAdapter)这个BaseAdapter的衍生类里。代码如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 计算gridview高度 
  3.      * @param gridView 
  4.      */  
  5.     public static void setGridViewHeightBasedOnChildren(GridView gridView) {  
  6.         // 获取GridView对应的Adapter  
  7.         ListAdapter listAdapter = gridView.getAdapter();  
  8.         if (listAdapter == null) {  
  9.             return;  
  10.         }  
  11.         int rows;  
  12.         int columns = 0;  
  13.         int horizontalBorderHeight = 0;  
  14.         Class<?> clazz = gridView.getClass();  
  15.         try {  
  16.             // 利用反射,取得每行显示的个数  
  17.             Field column = clazz.getDeclaredField("mRequestedNumColumns");  
  18.             column.setAccessible(true);  
  19.             columns = (Integer) column.get(gridView);  
  20.             // 利用反射,取得横向分割线高度  
  21.             Field horizontalSpacing = clazz  
  22.                     .getDeclaredField("mRequestedHorizontalSpacing");  
  23.             horizontalSpacing.setAccessible(true);  
  24.             horizontalBorderHeight = (Integer) horizontalSpacing.get(gridView);  
  25.         } catch (Exception e) {  
  26.             // TODO: handle exception  
  27.             e.printStackTrace();  
  28.         }  
  29.         // 判断数据总数除以每行个数是否整除。不能整除代表有多余,需要加一行  
  30.         if (listAdapter.getCount() % columns > 0) {  
  31.             rows = listAdapter.getCount() / columns + 1;  
  32.         } else {  
  33.             rows = listAdapter.getCount() / columns;  
  34.         }  
  35.         int totalHeight = 0;  
  36.         for (int i = 0; i < rows; i++) { // 只计算每项高度*行数  
  37.             View listItem = listAdapter.getView(i, null, gridView);  
  38.             listItem.measure(00); // 计算子项View 的宽高  
  39.             totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度  
  40.         }  
  41.         ViewGroup.LayoutParams params = gridView.getLayoutParams();  
  42.         params.height = totalHeight + horizontalBorderHeight * (rows - 1);// 最后加上分割线总高度  
  43.         gridView.setLayoutParams(params);  
  44.     }  
这样我们就可以在ListView中添加GridView了。。。

注:两个SrcollView型的控件可以是:

<ListView, GridView>;

<GridView,ListView>;

<ListView,ListView>;

<GridView, GridView>;

<ListView, ScrollView>;

<ScrollView,ListView>;

<GridView, ScrollView>;

<ScrollView, GridView>;

<ScrollView, ScrollView>;

... ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值