Android在ListView中嵌套一个GridView时只显示一行的原因及解决方法
? ? ? ? 在之前的編程里,我還沒有遇到過要在一個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的高度,然后計算總高度。具體代碼如下:
/*** 重新計算listView高度* @param listView*/public static void setListViewHeightBasedOnChildren(ListView listView) {// 獲取ListView對應的AdapterListAdapter listAdapter = listView.getAdapter();if (listAdapter == null) {return;}int totalHeight = 0;for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回數據項的數目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() * (listAdapter.getCount() - 1));// listView.getDividerHeight()獲取子項間分隔符占用的高度// params.height最后得到整個ListView完整顯示需要的高度listView.setLayoutParams(params);}在我們setAdapter()的之前,我們調用上面的方法,如setListViewHeightBasedOnChildren(accomplishmentStateListView);
因為我是在ListView中嵌套GridView,所以重新計算GridView的總高度的時候,要放在setAdapter(...GridViewAdapter)這個BaseAdapter的衍生類里。代碼如下:
/*** 計算gridview高度* @param gridView*/public static void setGridViewHeightBasedOnChildren(GridView gridView) {// 獲取GridView對應的AdapterListAdapter 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) {// TODO: handle exceptione.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); // 計算子項View 的寬高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>;
... ...
總結
以上是生活随笔為你收集整理的Android在ListView中嵌套一个GridView时只显示一行的原因及解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android中基于TCP协议的网络通信
- 下一篇: Android:ListView常见错位