可勾选的ExpandableListView

来源:互联网 发布:如何做淘宝客服兼职 编辑:程序博客网 时间:2024/06/06 14:16


加上checkbox,需求大抵都是:check group, check all his children; if one' group's children all checked, group become checked. ExpandableListView的选中状态没有类似SparseBooleanArray的东东,需要自己维护一个数据结构. 开发上要求点group list item的大多数区域是expand/collapse,仅点checkbox区域是勾选,而点child list item的任意区域都是勾选效果, 可以让列表setOnChildClickListener()。注意ExpandableListAdapter的isChildSelectable()方法一定返回true。

编辑自http://www.allenj.net/?p=3644. 给出干货:

EListAdapter.java

[java] view plaincopy
  1. package com.example.checkableexpandablelistview;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.content.Context;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.View.OnClickListener;  
  9. import android.view.ViewGroup;  
  10. import android.widget.BaseExpandableListAdapter;  
  11. import android.widget.CheckBox;  
  12. import android.widget.ExpandableListView;  
  13. import android.widget.TextView;  
  14.   
  15. import com.example.aexpandablelist.R;  
  16.   
  17. public class EListAdapter extends BaseExpandableListAdapter implements ExpandableListView.OnChildClickListener {  
  18.       
  19.     private Context context;  
  20.     private ArrayList<Group> groups;  
  21.    
  22.     public EListAdapter(Context context, ArrayList<Group> groups) {  
  23.         this.context = context;  
  24.         this.groups = groups;  
  25.     }  
  26.    
  27.     public Object getChild(int groupPosition, int childPosition) {  
  28.         return groups.get(groupPosition).getChildItem(childPosition);  
  29.     }  
  30.    
  31.     public long getChildId(int groupPosition, int childPosition) {  
  32.         return childPosition;  
  33.     }  
  34.    
  35.     public int getChildrenCount(int groupPosition) {  
  36.         return groups.get(groupPosition).getChildrenCount();  
  37.     }  
  38.    
  39.     public Object getGroup(int groupPosition) {  
  40.         return groups.get(groupPosition);  
  41.     }  
  42.    
  43.     public int getGroupCount() {  
  44.         return groups.size();  
  45.     }  
  46.    
  47.     public long getGroupId(int groupPosition) {  
  48.         return groupPosition;  
  49.     }  
  50.    
  51.     public boolean hasStableIds() {  
  52.         return true;  
  53.     }  
  54.    
  55.     public boolean isChildSelectable(int groupPosition, int childPosition) {  
  56.         return true;  
  57.     }  
  58.    
  59.     /** 設定 Group 資料 */  
  60.     public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {  
  61.         Group group = (Group) getGroup(groupPosition);  
  62.    
  63.         if (convertView == null) {  
  64.             LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  65.             convertView = infalInflater.inflate(R.layout.group_layout, null);  
  66.         }  
  67.    
  68.         TextView tv = (TextView) convertView.findViewById(R.id.tvGroup);  
  69.         tv.setText(group.getTitle());  
  70.    
  71.         // 重新產生 CheckBox 時,將存起來的 isChecked 狀態重新設定  
  72.         CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.chbGroup);  
  73.         checkBox.setChecked(group.getChecked());  
  74.    
  75.         // 點擊 CheckBox 時,將狀態存起來  
  76.         checkBox.setOnClickListener(new Group_CheckBox_Click(groupPosition));  
  77.    
  78.         return convertView;  
  79.     }  
  80.    
  81.     /** 勾選 Group CheckBox 時,存 Group CheckBox 的狀態,以及改變 Child CheckBox 的狀態 */  
  82.     class Group_CheckBox_Click implements OnClickListener {  
  83.         private int groupPosition;  
  84.    
  85.         Group_CheckBox_Click(int groupPosition) {  
  86.             this.groupPosition = groupPosition;  
  87.         }  
  88.    
  89.         public void onClick(View v) {  
  90.             groups.get(groupPosition).toggle();  
  91.    
  92.             // 將 Children 的 isChecked 全面設成跟 Group 一樣  
  93.             int childrenCount = groups.get(groupPosition).getChildrenCount();  
  94.             boolean groupIsChecked = groups.get(groupPosition).getChecked();  
  95.             for (int i = 0; i < childrenCount; i++)  
  96.                 groups.get(groupPosition).getChildItem(i).setChecked(groupIsChecked);  
  97.    
  98.             // 注意,一定要通知 ExpandableListView 資料已經改變,ExpandableListView 會重新產生畫面  
  99.             notifyDataSetChanged();  
  100.         }  
  101.     }  
  102.    
  103.     /** 設定 Children 資料 */  
  104.     public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {  
  105.         Child child = groups.get(groupPosition).getChildItem(childPosition);  
  106.    
  107.         if (convertView == null) {  
  108.             LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  109.             convertView = inflater.inflate(R.layout.child_layout, null);  
  110.         }  
  111.    
  112.         TextView tv = (TextView) convertView.findViewById(R.id.tvChild);  
  113.         tv.setText(child.getFullname());  
  114.    
  115.         // 重新產生 CheckBox 時,將存起來的 isChecked 狀態重新設定  
  116.         CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.chbChild);  
  117.         checkBox.setChecked(child.getChecked());  
  118.    
  119.         // 點擊 CheckBox 時,將狀態存起來  
  120.         checkBox.setOnClickListener(new Child_CheckBox_Click(groupPosition, childPosition));  
  121.    
  122.         return convertView;  
  123.     }  
  124.    
  125.     /** 勾選 Child CheckBox 時,存 Child CheckBox 的狀態 */  
  126.     class Child_CheckBox_Click implements OnClickListener {  
  127.         private int groupPosition;  
  128.         private int childPosition;  
  129.    
  130.         Child_CheckBox_Click(int groupPosition, int childPosition) {  
  131.             this.groupPosition = groupPosition;  
  132.             this.childPosition = childPosition;  
  133.         }  
  134.    
  135.         public void onClick(View v) {  
  136.             handleClick(childPosition, groupPosition);  
  137.         }  
  138.     }  
  139.       
  140.     public void handleClick(int childPosition, int groupPosition) {  
  141.         groups.get(groupPosition).getChildItem(childPosition).toggle();  
  142.           
  143.         // 檢查 Child CheckBox 是否有全部勾選,以控制 Group CheckBox  
  144.         int childrenCount = groups.get(groupPosition).getChildrenCount();  
  145.         boolean childrenAllIsChecked = true;  
  146.         for (int i = 0; i < childrenCount; i++) {  
  147.             if (!groups.get(groupPosition).getChildItem(i).getChecked())  
  148.                 childrenAllIsChecked = false;  
  149.         }  
  150.   
  151.         groups.get(groupPosition).setChecked(childrenAllIsChecked);  
  152.   
  153.         // 注意,一定要通知 ExpandableListView 資料已經改變,ExpandableListView 會重新產生畫面  
  154.         notifyDataSetChanged();  
  155.     }  
  156.   
  157.     @Override  
  158.     public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {  
  159.         handleClick(childPosition, groupPosition);  
  160.         return true;  
  161.     }  
  162.       
  163. }  

Group.java

[java] view plaincopy
  1. package com.example.checkableexpandablelistview;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class Group {  
  6.     private String id;  
  7.     private String title;  
  8.     private ArrayList<Child> children;  
  9.     private boolean isChecked;  
  10.    
  11.     public Group(String id, String title) {  
  12.         this.title = title;  
  13.         children = new ArrayList<Child>();  
  14.         this.isChecked = false;  
  15.     }  
  16.    
  17.     public void setChecked(boolean isChecked) {  
  18.         this.isChecked = isChecked;  
  19.     }  
  20.    
  21.     public void toggle() {  
  22.         this.isChecked = !this.isChecked;  
  23.     }  
  24.    
  25.     public boolean getChecked() {  
  26.         return this.isChecked;  
  27.     }  
  28.    
  29.     public String getId() {  
  30.         return id;  
  31.     }  
  32.    
  33.     public String getTitle() {  
  34.         return title;  
  35.     }  
  36.    
  37.     public void addChildrenItem(Child child) {  
  38.         children.add(child);  
  39.     }  
  40.    
  41.     public int getChildrenCount() {  
  42.         return children.size();  
  43.     }  
  44.    
  45.     public Child getChildItem(int index) {  
  46.         return children.get(index);  
  47.     }  
  48. }  



Child.java

[java] view plaincopy
  1. package com.example.checkableexpandablelistview;  
  2.   
  3. public class Child {  
  4.     private String userid;  
  5.     private String fullname;  
  6.     private String username;  
  7.     private boolean isChecked;  
  8.    
  9.     public Child(String userid, String fullname, String username) {  
  10.         this.userid = userid;  
  11.         this.fullname = fullname;  
  12.         this.username = username;  
  13.         this.isChecked = false;  
  14.     }  
  15.    
  16.     public void setChecked(boolean isChecked) {  
  17.         this.isChecked = isChecked;  
  18.     }  
  19.    
  20.     public void toggle() {  
  21.         this.isChecked = !this.isChecked;  
  22.     }  
  23.    
  24.     public boolean getChecked() {  
  25.         return this.isChecked;  
  26.     }  
  27.    
  28.     public String getUserid() {  
  29.         return userid;  
  30.     }  
  31.    
  32.     public String getFullname() {  
  33.         return fullname;  
  34.     }  
  35.    
  36.     public String getUsername() {  
  37.         return username;  
  38.     }  
  39. }  


MainActivity.java

[java] view plaincopy
  1. package com.example.checkableexpandablelistview;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import org.json.JSONArray;  
  6. import org.json.JSONException;  
  7. import org.json.JSONObject;  
  8.   
  9. import android.app.Activity;  
  10. import android.os.Bundle;  
  11. import android.util.Log;  
  12. import android.view.Menu;  
  13. import android.widget.ExpandableListView;  
  14.   
  15. import com.example.aexpandablelist.R;  
  16.   
  17.   
  18. public class MainActivity extends Activity {  
  19.   
  20.     ArrayList<Group> groups;  
  21.     ExpandableListView listView;  
  22.     EListAdapter adapter;  
  23.       
  24.     @Override  
  25.     public void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.activity_main);  
  28.   
  29.         groups = new ArrayList<Group>();  
  30.         getJSONObject();  
  31.         listView = (ExpandableListView) findViewById(R.id.listView);  
  32.         adapter = new EListAdapter(this, groups);  
  33.         listView.setAdapter(adapter);  
  34.         listView.setOnChildClickListener(adapter);  
  35.     }  
  36.   
  37.     /** 解悉 JSON 字串 */  
  38.     private void getJSONObject() {  
  39.         String jsonStr = "{'CommunityUsersResult':[{'CommunityUsersList':[{'fullname':'a111','userid':11,'username':'a1'}"  
  40.                 + ",{'fullname':'b222','userid':12,'username':'b2'}],'id':1,'title':'人事部'},{'CommunityUsersList':[{'fullname':"  
  41.                 + "'c333','userid':13,'username':'c3'},{'fullname':'d444','userid':14,'username':'d4'},{'fullname':'e555','userid':"  
  42.                 + "15,'username':'e5'}],'id':2,'title':'開發部'}]}";  
  43.   
  44.         try {  
  45.             JSONObject CommunityUsersResultObj = new JSONObject(jsonStr);  
  46.             JSONArray groupList = CommunityUsersResultObj.getJSONArray("CommunityUsersResult");  
  47.   
  48.             for (int i = 0; i < groupList.length(); i++) {  
  49.                 JSONObject groupObj = (JSONObject) groupList.get(i);  
  50.                 Group group = new Group(groupObj.getString("id"), groupObj.getString("title"));  
  51.                 JSONArray childrenList = groupObj.getJSONArray("CommunityUsersList");  
  52.   
  53.                 for (int j = 0; j < childrenList.length(); j++) {  
  54.                     JSONObject childObj = (JSONObject) childrenList.get(j);  
  55.                     Child child = new Child(childObj.getString("userid"), childObj.getString("fullname"),  
  56.                             childObj.getString("username"));  
  57.                     group.addChildrenItem(child);  
  58.                 }  
  59.   
  60.                 groups.add(group);  
  61.             }  
  62.         } catch (JSONException e) {  
  63.             Log.d("allenj", e.toString());  
  64.         }  
  65.     }  
  66.   
  67.     @Override  
  68.     public boolean onCreateOptionsMenu(Menu menu) {  
  69.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  70.         return true;  
  71.     }  
  72. }  


activity_main.xml

[java] view plaincopy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <ExpandableListView  
  7.         android:id="@+id/listView"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content" >  
  10.     </ExpandableListView>  
  11.   
  12. </RelativeLayout>  

group_layout.xml

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="horizontal" >  
  6.   
  7.     <TextView  
  8.         android:id="@+id/tvGroup"  
  9.         android:layout_width="280dp"  
  10.         android:layout_height="45dip"  
  11.         android:gravity="center_vertical|left"  
  12.         android:paddingLeft="45dp"  
  13.         android:textSize="17dip"  
  14.         android:textStyle="bold" >  
  15.     </TextView>  
  16.   
  17.     <CheckBox  
  18.         android:id="@+id/chbGroup"  
  19.         android:layout_width="wrap_content"  
  20.         android:layout_height="wrap_content"  
  21.         android:focusable="false" />  
  22.   
  23. </LinearLayout>  

child_layout.xml

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="horizontal" >  
  6.   
  7.     <TextView  
  8.         android:id="@+id/tvChild"  
  9.         android:layout_width="280dp"  
  10.         android:layout_height="45dip"  
  11.         android:gravity="center_vertical"  
  12.         android:paddingLeft="45dp"  
  13.         android:textSize="17dip"  
  14.         android:textStyle="bold" >  
  15.     </TextView>  
  16.   
  17.     <CheckBox  
  18.         android:id="@+id/chbChild"  
  19.         android:layout_width="wrap_content"  
  20.         android:layout_height="wrap_content"  
  21.         android:clickable="false"  
  22.         android:focusable="false" />  
  23.   
  24. </LinearLayout>  
0 0