现在的位置: 首页 > 综合 > 正文

ExpandableListView扩展(BaseExpandableListAdapter的使用)

2013年06月11日 ⁄ 综合 ⁄ 共 13627字 ⁄ 字号 评论关闭

针对普通的ExpandableListView的使用,即,需要显示的数据全都是使用TextView显示时,我们使用SimpleExpandableListAdapter就可以了。

但是如果是相对复杂的ExpandableListView,那么SimpleExpandableListAdapter就不满足我们的要求。

例如:在ExpandableListView中使用CheckBox控件。

这时候,我们就必须自己写一个Adapter来使用。方法是继承BaseExpandableListAdapter

 

layout/main.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"   
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent">  
  6.     <ExpandableListView   
  7.         android:id="@id/android:list"  
  8.         android:layout_width="fill_parent"   
  9.         android:layout_height="fill_parent">  
  10.     </ExpandableListView>  
  11.     <TextView   
  12.         android:layout_width="fill_parent"  
  13.         android:layout_height="fill_parent"   
  14.         android:id="@id/android:empty"  
  15.         android:text="No Data" />  
  16. </LinearLayout>  

layout/groups.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"   
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <TextView   
  7.         android:id="@+id/groupTextView"  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="fill_parent"   
  10.         android:textSize="25sp"   
  11.         android:paddingLeft="35px"   
  12.         android:paddingTop="10px"  
  13.         android:paddingRight="5px"   
  14.         android:paddingBottom="10px"   
  15.         android:text="No Data" />  
  16. </LinearLayout>  

layout/childs.xml(其实英文名字应该是children才对)

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent">  
  5.     <TextView   
  6.         android:id="@+id/childTextView"  
  7.         android:layout_width="wrap_content"  
  8.         android:layout_height="match_parent"  
  9.         android:layout_alignParentLeft="true"  
  10.         android:textSize="22sp"  
  11.         android:layout_marginLeft="30dip"  
  12.         android:layout_marginTop="5dip"  
  13.         android:text="No Data" />  
  14.     <CheckBox   
  15.         android:id="@+id/childCheckBox"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="match_parent"  
  18.         android:layout_alignParentRight="true"  
  19.         android:layout_marginLeft="50dip"/>  
  20. </RelativeLayout>  

主类ExpandableListViewActivity.java

  1. package com.zeph.android.expandablelistview.example;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7.   
  8. import android.app.ExpandableListActivity;  
  9. import android.os.Bundle;  
  10. import android.view.View;  
  11. import android.widget.ExpandableListView;  
  12.   
  13. public class ExpandableListViewActivity extends ExpandableListActivity {  
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.   
  19.         // 创建两个一级条目标题  
  20.         List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();  
  21.         Map<String, String> groupData1 = new HashMap<String, String>();  
  22.         groupData1.put("groupTextView""新闻");// group对应layout中的id:group  
  23.         Map<String, String> groupData2 = new HashMap<String, String>();  
  24.         groupData2.put("groupTextView""科技");  
  25.         groupData.add(groupData1);  
  26.         groupData.add(groupData2);  
  27.   
  28.         // 创建第一个一级条目下的的二级条目  
  29.         List<Map<String, Object>> child1 = new ArrayList<Map<String, Object>>();  
  30.         Map<String, Object> childData1 = new HashMap<String, Object>();  
  31.         childData1.put("childTextView""网易头条新闻");// 同理  
  32.         childData1.put("childCheckBox"0);// 同理  
  33.         Map<String, Object> childData2 = new HashMap<String, Object>();  
  34.         childData2.put("childTextView""凤凰网新闻");  
  35.         childData2.put("childCheckBox"1);  
  36.         child1.add(childData1);  
  37.         child1.add(childData2);  
  38.   
  39.         // 创建第二个一级条目下的的二级条目  
  40.         List<Map<String, Object>> child2 = new ArrayList<Map<String, Object>>();  
  41.         Map<String, Object> childData3 = new HashMap<String, Object>();  
  42.         childData3.put("childTextView""TechWeb");  
  43.         childData3.put("childCheckBox"0);  
  44.         Map<String, Object> childData4 = new HashMap<String, Object>();  
  45.         childData4.put("childTextView""月光博客");  
  46.         childData4.put("childCheckBox"1);  
  47.         child2.add(childData3);  
  48.         child2.add(childData4);  
  49.   
  50.         // 将二级条目放在一个集合里,供显示时使用  
  51.         List<List<Map<String, Object>>> childData = new ArrayList<List<Map<String, Object>>>();  
  52.         childData.add(child1);  
  53.         childData.add(child2);  
  54.         MyExpandableListViewAdapter adapter = new MyExpandableListViewAdapter(  
  55.                 getApplicationContext(), groupData, R.layout.groups,  
  56.                 new String[] { "groupTextView" },  
  57.                 new int[] { R.id.groupTextView }, childData, R.layout.childs,  
  58.                 new String[] { "childTextView""childCheckBox" }, new int[] {  
  59.                         R.id.childTextView, R.id.childCheckBox });  
  60.         setListAdapter(adapter);  
  61.     }  
  62.   
  63.     /** 
  64.      * 设置哪个二级目录被默认选中 
  65.      */  
  66.     @Override  
  67.     public boolean setSelectedChild(int groupPosition, int childPosition,  
  68.             boolean shouldExpandGroup) {  
  69.         // do something  
  70.         return super.setSelectedChild(groupPosition, childPosition,  
  71.                 shouldExpandGroup);  
  72.     }  
  73.   
  74.     /** 
  75.      * 设置哪个一级目录被默认选中 
  76.      */  
  77.     @Override  
  78.     public void setSelectedGroup(int groupPosition) {  
  79.         // do something  
  80.         super.setSelectedGroup(groupPosition);  
  81.     }  
  82.   
  83.     /** 
  84.      * 当二级条目被点击时响应 
  85.      */  
  86.     @Override  
  87.     public boolean onChildClick(ExpandableListView parent, View v,  
  88.             int groupPosition, int childPosition, long id) {  
  89.         // do something  
  90.         return super.onChildClick(parent, v, groupPosition, childPosition, id);  
  91.     }  
  92.   
  93. }  

Adapter类,MyExpandableListViewAdapter.java

  1. package com.zeph.android.expandablelistview.example;  
  2.   
  3. import java.util.List;  
  4. import java.util.Map;  
  5.   
  6. import android.content.Context;  
  7. import android.view.LayoutInflater;  
  8. import android.view.View;  
  9. import android.view.ViewGroup;  
  10. import android.widget.BaseExpandableListAdapter;  
  11. import android.widget.CheckBox;  
  12. import android.widget.TextView;  
  13.   
  14. /** 
  15.  * 首个List对应子元素中所代表的组,第二个List对应孙子元素在子元素组中的位置. Map亦将支持这样的特殊元素。(子元素嵌套组元素的情况) 
  16.  * 将XML文件中定义的静态数据映射到组及其视图的简单的适配器. 你可以用 Map的列表,为组指定其后台数据。每个数组元素对应一个可展开列表的一个组。 
  17.  * Maps 包含每行的数据。你还可以指定 XML 文件来定义用于显示组的视图, 并通过 Map 的键值映射到指定的视图。该过程适用于组的子元素。 
  18.  * 单级以外的可展开列表的后台数据类型为List<List<Map>>, 
  19.  * 第一级列表对应可扩展视图组中的组视图,第二级列表对应组的子组视图, 最后 Map 保持子组视图的子视图的数据。 
  20.  *  
  21.  * @author BenZeph (以下代码和注释均参考了工具屋,网址:http://code.google.com/p/toolib/) 
  22.  */  
  23. public class MyExpandableListViewAdapter extends BaseExpandableListAdapter {  
  24.   
  25.     private List<? extends Map<String, ?>> mGroupData;  
  26.     private int mExpandedGroupLayout;  
  27.     private int mCollapsedGroupLayout;  
  28.     private String[] mGroupFrom;  
  29.     private int[] mGroupTo;  
  30.   
  31.     private List<? extends List<? extends Map<String, ?>>> mChildData;  
  32.     private int mChildLayout;  
  33.     private int mLastChildLayout;  
  34.     private String[] mChildFrom;  
  35.     private int[] mChildTo;  
  36.   
  37.     private LayoutInflater mInflater;  
  38.   
  39.     /** 
  40.      * 调用另外一个构造函数,其中From和To的含义和不同的ListView相同, 
  41.      * 可以参考ListView或者SimpleExpandableListViewAdapter 
  42.      *  
  43.      * @param context 
  44.      * @param groupData 
  45.      * @param groupLayout 
  46.      * @param groupFrom 
  47.      * @param groupTo 
  48.      * @param childData 
  49.      * @param childLayout 
  50.      * @param childFrom 
  51.      * @param childTo 
  52.      */  
  53.     public MyExpandableListViewAdapter(Context context,  
  54.             List<? extends Map<String, ?>> groupData, int groupLayout,  
  55.             String[] groupFrom, int[] groupTo,  
  56.             List<? extends List<? extends Map<String, ?>>> childData,  
  57.             int childLayout, String[] childFrom, int[] childTo) {  
  58.         this(context, groupData, groupLayout, groupLayout, groupFrom, groupTo,  
  59.                 childData, childLayout, childLayout, childFrom, childTo);  
  60.     }  
  61.   
  62.     /** 
  63.      *  
  64.      * @param context 
  65.      * @param groupData 
  66.      * @param expandedGroupLayout 
  67.      * @param collapsedGroupLayout 
  68.      * @param groupFrom 
  69.      * @param groupTo 
  70.      * @param childData 
  71.      * @param childLayout 
  72.      * @param lastChildLayout 
  73.      * @param childFrom 
  74.      * @param childTo 
  75.      */  
  76.     public MyExpandableListViewAdapter(Context context,  
  77.             List<? extends Map<String, ?>> groupData, int expandedGroupLayout,  
  78.             int collapsedGroupLayout, String[] groupFrom, int[] groupTo,  
  79.             List<? extends List<? extends Map<String, ?>>> childData,  
  80.             int childLayout, int lastChildLayout, String[] childFrom,  
  81.             int[] childTo) {  
  82.         mGroupData = groupData;  
  83.         mExpandedGroupLayout = expandedGroupLayout;  
  84.         mCollapsedGroupLayout = collapsedGroupLayout;  
  85.         mGroupFrom = groupFrom;  
  86.         mGroupTo = groupTo;  
  87.         mChildData = childData;  
  88.         mChildLayout = childLayout;  
  89.         mLastChildLayout = lastChildLayout;  
  90.         mChildFrom = childFrom;  
  91.         mChildTo = childTo;  
  92.         mInflater = (LayoutInflater) context  
  93.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  94.     }  
  95.   
  96.     @Override  
  97.     public Object getChild(int groupPosition, int childPosition) {  
  98.         // 取得与指定分组、指定子项目关联的数据。  
  99.         return mChildData.get(groupPosition).get(childPosition);  
  100.     }  
  101.   
  102.     @Override  
  103.     public long getChildId(int groupPosition, int childPosition) {  
  104.         // 取得给定分组中给定子视图的ID。 该组ID必须在组中是唯一的。组合的ID (参见getCombinedGroupId(long))  
  105.         // 必须不同于其他所有ID(分组及子项目的ID)。  
  106.         return childPosition;  
  107.     }  
  108.   
  109.     @Override  
  110.     public View getChildView(int groupPosition, int childPosition,  
  111.             boolean isLastChild, View convertView, ViewGroup parent) {  
  112.         // 取得显示给定分组给定子位置的数据用的视图。  
  113.         View v;  
  114.         if (convertView == null) {  
  115.             v = newChildView(isLastChild, parent);  
  116.         } else {  
  117.             v = convertView;  
  118.         }  
  119.         bindChildView(v, mChildData.get(groupPosition).get(childPosition),  
  120.                 mChildFrom, mChildTo);  
  121.         return v;  
  122.     }  
  123.   
  124.     @Override  
  125.     public int getChildrenCount(int groupPosition) {  
  126.         // 取得指定分组的子元素数。  
  127.         return mChildData.get(groupPosition).size();  
  128.     }  
  129.   
  130.     @Override  
  131.     public Object getGroup(int groupPosition) {  
  132.         // 取得与给定分组关联的数据。  
  133.         return mGroupData.get(groupPosition);  
  134.     }  
  135.   
  136.     @Override  
  137.     public int getGroupCount() {  
  138.         // 取得分组数  
  139.         return mChildData.size();  
  140.     }  
  141.   
  142.     @Override  
  143.     public long getGroupId(int groupPosition) {  
  144.         // 取得指定分组的ID。该组ID必须在组中是唯一的。组合的ID (参见getCombinedGroupId(long))  
  145.         // 必须不同于其他所有ID(分组及子项目的ID)。  
  146.         return groupPosition;  
  147.     }  
  148.   
  149.     @Override  
  150.     public View getGroupView(int groupPosition, boolean isExpanded,  
  151.             View convertView, ViewGroup parent) {  
  152.         // 取得用于显示给定分组的视图。 这个方法仅返回分组的视图对象, 要想获取子元素的视图对象,  
  153.         // 就需要调用 getChildView(int, int, boolean, View, ViewGroup)。  
  154.         View v;  
  155.         if (convertView == null) {  
  156.             v = newGroupView(isExpanded, parent);  
  157.         } else {  
  158.             v = convertView;  
  159.         }  
  160.         bindGroupView(v, mGroupData.get(groupPosition), mGroupFrom, mGroupTo);  
  161.         return v;  
  162.     }  
  163.   
  164.     @Override  
  165.     public boolean hasStableIds() {  
  166.         // 是否指定分组视图及其子视图的ID对应的后台数据改变也会保持该ID。  
  167.         return true;  
  168.     }  
  169.   
  170.     @Override  
  171.     public boolean isChildSelectable(int groupPosition, int childPosition) {  
  172.         // 指定位置的子视图是否可选择。  
  173.         return true;  
  174.     }  
  175.   
  176.     /** 
  177.      * 创建新的组视图 
  178.      *  
  179.      * @param isExpanded 
  180.      * @param parent 
  181.      * @return 
  182.      */  
  183.     public View newGroupView(boolean isExpanded, ViewGroup parent) {  
  184.         return mInflater.inflate((isExpanded) ? mExpandedGroupLayout  
  185.                 : mCollapsedGroupLayout, parent, false);  
  186.     }  
  187.   
  188.     /** 
  189.      * 创建新的子视图 
  190.      *  
  191.      * @param isLastChild 
  192.      * @param parent 
  193.      * @return 
  194.      */  
  195.     public View newChildView(boolean isLastChild, ViewGroup parent) {  
  196.         return mInflater.inflate((isLastChild) ? mLastChildLayout  
  197.                 : mChildLayout, parent, false);  
  198.     }  
  199.   
  200.     /** 
  201.      * 绑定组数据 
  202.      *  
  203.      * @param view 
  204.      * @param data 
  205.      * @param from 
  206.      * @param to 
  207.      */  
  208.     private void bindGroupView(View view, Map<String, ?> data, String[] from,  
  209.             int[] to) {  
  210.         // 绑定组视图的数据,针对Group的Layout都是TextView的情况  
  211.         int len = to.length;  
  212.         for (int i = 0; i < len; i++) {  
  213.             TextView v = (TextView) view.findViewById(to[i]);  
  214.             if (v != null) {  
  215.                 v.setText((String) data.get(from[i]));  
  216.             }  
  217.         }  
  218.     }  
  219.   
  220.     /** 
  221.      * 绑定子数据 
  222.      *  
  223.      * @param view 
  224.      * @param data 
  225.      * @param from 
  226.      * @param to 
  227.      */  
  228.     private void bindChildView(View view, Map<String, ?> data, String[] from,  
  229.             int[] to) {  
  230.         TextView v = (TextView) view.findViewById(to[0]);  
  231.         if (v != null) {  
  232.             v.setText((String) data.get(from[0]));  
  233.         }  
  234.         CheckBox c = (CheckBox) view.findViewById(to[1]);  
  235.         if (c != null) {  
  236.             if (data.get(from[1]).equals(0)) {  
  237.                 c.setChecked(true);  
  238.             } else {  
  239.                 c.setChecked(false);  
  240.             }  
  241.         }  
  242.     }  
  243. }  

 

程序本身还存在问题,checkbox在点击修改了状态之后,缩小组,在展开组,checkbox的状态会还原。

这是因为,在点击展开时,会重新调用getChildView函数,于是子列表的中的数据重新初始化了。所以数据就还原了。

因此,这个位置的代码还需要修改。才能满足要求。

转载自 http://blog.csdn.net/benw1988/article/details/6871244

抱歉!评论已关闭.