ScrollView中嵌套使用ListView,GridView

 出處:http://m.blog.csdn.net/blog/yhc13429826359/39058973

在之前的編程裏,我還沒有遇到過要在一個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的高度,然後計算總高度。具體代碼如下:

<span style="white-space:pre">	</span>/**
	 * 重新計算listView高度
	 * @param listView
	 */
	public static void setListViewHeightBasedOnChildren(ListView listView) {
		// 獲取ListView對應的Adapter
		ListAdapter 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的衍生類裏。代碼如下:

<span style="white-space:pre">	</span>/**
	 * 計算gridview高度
	 * @param gridView
	 */
	public static void setGridViewHeightBasedOnChildren(GridView gridView) {
		// 獲取GridView對應的Adapter
		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) {
			// TODO: handle exception
			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); // 計算子項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>;

發佈了31 篇原創文章 · 獲贊 43 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章