1. 程式人生 > >【Android基礎】ExpandableListView巢狀ListView

【Android基礎】ExpandableListView巢狀ListView

ExpandableListView是一個垂直滾動顯示兩級列表項的檢視,與ListView不同的是,它可以有兩層:每一層都能夠被獨立的展開並顯示其子項。這些子項來自於與該檢視關聯的BaseExpandableListAdapter。

有時候簡單的ExpandableListView不能滿足我們的需求,比如下面這樣的需求:

這就需要在ExpandableListView裡面再巢狀一個ListView來實現。首先需要重寫一個ListView,程式碼如下:

public class SubListView extends ListView {
	public SubListView(android.content.Context context,
			android.util.AttributeSet attrs) {
		super(context, attrs);
	}

	
	public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
				MeasureSpec.AT_MOST);
		super.onMeasure(widthMeasureSpec, expandSpec);

	}

}

主要是重寫onMeasure方法,這裡將heightMeasureSpec引數設大,否則,巢狀的ListView會顯示不全。

然後重寫我們的BaseExpandableListAdapter,程式碼如下:

class ExpandAdapter extends BaseExpandableListAdapter {
		private Context context;
		private ArrayList<ArrayList<String>> childList;
		private ArrayList<String> groupList;
		private LayoutInflater inflater;

		public ExpandAdapter(Context context, ArrayList<String> groupList,
				ArrayList<ArrayList<String>> childList) {
			this.childList = childList;
			this.groupList = groupList;
			this.context = context;
			inflater = LayoutInflater.from(context);
		}

		@Override
		public int getGroupCount() {
			// TODO Auto-generated method stub
			return groupList.size();
		}

		@Override
		public int getChildrenCount(int groupPosition) {
			// TODO Auto-generated method stub
			// return childList.get(groupPosition).size();
			return 1;
		}

		@Override
		public Object getGroup(int groupPosition) {
			// TODO Auto-generated method stub
			return groupList.get(groupPosition);
		}

		@Override
		public Object getChild(int groupPosition, int childPosition) {
			// TODO Auto-generated method stub
			return childList.get(groupPosition).get(childPosition);
		}

		@Override
		public long getGroupId(int groupPosition) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public long getChildId(int groupPosition, int childPosition) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public boolean hasStableIds() {
			// TODO Auto-generated method stub
			return true;
		}

		@Override
		public View getGroupView(int groupPosition, boolean isExpanded,
				View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			View groupView = null;
			if (convertView == null) {
				groupView = newGroupView(parent);
			} else {
				groupView = convertView;
			}
			bindGroupView(groupPosition, groupView);
			return groupView;
		}

		private View newGroupView(ViewGroup parent) {
			return inflater.inflate(R.layout.group_item_layout, null);
		}

		private void bindGroupView(int groupPosition, View groupView) {
			TextView tv = (TextView) groupView.findViewById(R.id.name_text);
			tv.setText(groupList.get(groupPosition));
			ImageView iv = (ImageView) groupView
					.findViewById(R.id.image_avatar);
			iv.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					Toast.makeText(context, "Hello!", Toast.LENGTH_SHORT)
							.show();
				}

			});
		}

		@Override
		public View getChildView(int groupPosition, int childPosition,

		boolean isLastChild, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			View childView = null;
			if (convertView == null) {
				childView = newChildView(parent, groupPosition);
			} else {
				childView = convertView;
			}
			bindChildView(groupPosition, childPosition, childView);
			return childView;
		}

		private View newChildView(ViewGroup parent, final int groupPosition) {
			View v = inflater.inflate(R.layout.child_layout, null);
			SubListView listView = (SubListView) v.findViewById(R.id.sublistview);
			View foot = inflater.inflate(R.layout.foot_layout, null);
			listView.addFooterView(foot);
			// final SubListAdapter adapter = new
			// SubListAdapter(treeNodes.get(groupPosition).childs,layoutInflater);
			final SubListAdapter adapter = new SubListAdapter(
					childList.get(groupPosition), inflater);
			listView.setAdapter(adapter);// 設定選單Adapter
			listView.setOnItemClickListener(new OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> parent, View view,
						int position, long id) {
					// TODO Auto-generated method stub
					// if(position ==
					// treeNodes.get(groupPosition).childs.size()){//foot的點選事件處理
					// treeNodes.get(groupPosition).childs.add("New Add");
					// adapter.notifyDataSetChanged();
					// }else{
					// Toast.makeText(parentContext, "當前選中的是:" + position,
					// Toast.LENGTH_SHORT).show();
					// }
					if (position == childList.get(groupPosition).size()) {// foot的點選事件處理
						childList.get(groupPosition).add("New Add");
						adapter.notifyDataSetChanged();
					} else {
						Toast.makeText(ExpandableListViewActivity.this,
								"當前選中的是:" + position, Toast.LENGTH_SHORT)
								.show();
					}
				}

			});
			return v;
		}

		private void bindChildView(int groupPosition, int childPosition,
				View groupView) {
//			TextView tv = (TextView) groupView.findViewById(R.id.name_text);
//			tv.setText(childList.get(groupPosition).get(childPosition));
		}

		@Override
		public boolean isChildSelectable(int groupPosition, int childPosition) {
			// TODO Auto-generated method stub
			return true;
		}

	}

這裡需要注意的是在getChildrenCount方法裡要返回1,不然就會每個二級View裡就會生成很多ListView。載入很多其實就是靠ListView的foot的點選事件來處理的。

這裡對ExpandableListView也做了一些其他的處理,一併記錄下。第一個是將一級View的指示符號放到裡右面並且進行了自定義。放到右面的方法如下:

<span style="font-size: 18px;">int width = getWindowManager().getDefaultDisplay().getWidth();
		expandableListView.setIndicatorBounds(width - 100, width - 10);</span>


自定義指示符的方法是在res/drawable下自定義一個xml命名為indicator.xml,如下:

<span style="font-size: 18px;"><?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
 <item android:state_expanded="true" android:drawable="@drawable/add_btn_small" />
 <item android:state_expanded="false" android:drawable="@drawable/head32_32" />
</selector></span>


然後在我們的layout裡做以下處理:

<span style="font-size: 18px;">android:groupIndicator="@drawable/indicator"</span>

這樣就會顯示我們自定義的View了,需要注意的一點是這裡的圖片容易拉伸,最好用.9的圖。

第二個問題是預設將ExpandableListView預設開啟,這個就比較簡單了,

private void expandView() {
		for (int i = 0; i < groupList.size(); i++) {
			expandableListView.expandGroup(i);
		}
	}