【Android基礎】ExpandableListView巢狀ListView
阿新 • • 發佈:2019-02-04
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);
}
}