可勾选的ExpandableListView


加上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

package com.example.checkableexpandablelistview;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.TextView;

import com.example.aexpandablelist.R;

public class EListAdapter extends BaseExpandableListAdapter implements ExpandableListView.OnChildClickListener {
    
    private Context context;
    private ArrayList<Group> groups;
 
    public EListAdapter(Context context, ArrayList<Group> groups) {
        this.context = context;
        this.groups = groups;
    }
 
    public Object getChild(int groupPosition, int childPosition) {
        return groups.get(groupPosition).getChildItem(childPosition);
    }
 
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }
 
    public int getChildrenCount(int groupPosition) {
        return groups.get(groupPosition).getChildrenCount();
    }
 
    public Object getGroup(int groupPosition) {
        return groups.get(groupPosition);
    }
 
    public int getGroupCount() {
        return groups.size();
    }
 
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }
 
    public boolean hasStableIds() {
        return true;
    }
 
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
 
    /** 設定 Group 資料 */
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        Group group = (Group) getGroup(groupPosition);
 
        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.group_layout, null);
        }
 
        TextView tv = (TextView) convertView.findViewById(R.id.tvGroup);
        tv.setText(group.getTitle());
 
        // 重新產生 CheckBox 時,將存起來的 isChecked 狀態重新設定
        CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.chbGroup);
        checkBox.setChecked(group.getChecked());
 
        // 點擊 CheckBox 時,將狀態存起來
        checkBox.setOnClickListener(new Group_CheckBox_Click(groupPosition));
 
        return convertView;
    }
 
    /** 勾選 Group CheckBox 時,存 Group CheckBox 的狀態,以及改變 Child CheckBox 的狀態 */
    class Group_CheckBox_Click implements OnClickListener {
        private int groupPosition;
 
        Group_CheckBox_Click(int groupPosition) {
            this.groupPosition = groupPosition;
        }
 
        public void onClick(View v) {
            groups.get(groupPosition).toggle();
 
            // 將 Children 的 isChecked 全面設成跟 Group 一樣
            int childrenCount = groups.get(groupPosition).getChildrenCount();
            boolean groupIsChecked = groups.get(groupPosition).getChecked();
            for (int i = 0; i < childrenCount; i++)
                groups.get(groupPosition).getChildItem(i).setChecked(groupIsChecked);
 
            // 注意,一定要通知 ExpandableListView 資料已經改變,ExpandableListView 會重新產生畫面
            notifyDataSetChanged();
        }
    }
 
    /** 設定 Children 資料 */
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        Child child = groups.get(groupPosition).getChildItem(childPosition);
 
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.child_layout, null);
        }
 
        TextView tv = (TextView) convertView.findViewById(R.id.tvChild);
        tv.setText(child.getFullname());
 
        // 重新產生 CheckBox 時,將存起來的 isChecked 狀態重新設定
        CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.chbChild);
        checkBox.setChecked(child.getChecked());
 
        // 點擊 CheckBox 時,將狀態存起來
        checkBox.setOnClickListener(new Child_CheckBox_Click(groupPosition, childPosition));
 
        return convertView;
    }
 
    /** 勾選 Child CheckBox 時,存 Child CheckBox 的狀態 */
    class Child_CheckBox_Click implements OnClickListener {
        private int groupPosition;
        private int childPosition;
 
        Child_CheckBox_Click(int groupPosition, int childPosition) {
            this.groupPosition = groupPosition;
            this.childPosition = childPosition;
        }
 
        public void onClick(View v) {
            handleClick(childPosition, groupPosition);
        }
    }
    
    public void handleClick(int childPosition, int groupPosition) {
        groups.get(groupPosition).getChildItem(childPosition).toggle();
        
        // 檢查 Child CheckBox 是否有全部勾選,以控制 Group CheckBox
        int childrenCount = groups.get(groupPosition).getChildrenCount();
        boolean childrenAllIsChecked = true;
        for (int i = 0; i < childrenCount; i++) {
            if (!groups.get(groupPosition).getChildItem(i).getChecked())
                childrenAllIsChecked = false;
        }

        groups.get(groupPosition).setChecked(childrenAllIsChecked);

        // 注意,一定要通知 ExpandableListView 資料已經改變,ExpandableListView 會重新產生畫面
        notifyDataSetChanged();
    }

    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        handleClick(childPosition, groupPosition);
        return true;
    }
    
}


Group.java

package com.example.checkableexpandablelistview;

import java.util.ArrayList;

public class Group {
    private String id;
    private String title;
    private ArrayList<Child> children;
    private boolean isChecked;
 
    public Group(String id, String title) {
        this.title = title;
        children = new ArrayList<Child>();
        this.isChecked = false;
    }
 
    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
    }
 
    public void toggle() {
        this.isChecked = !this.isChecked;
    }
 
    public boolean getChecked() {
        return this.isChecked;
    }
 
    public String getId() {
        return id;
    }
 
    public String getTitle() {
        return title;
    }
 
    public void addChildrenItem(Child child) {
        children.add(child);
    }
 
    public int getChildrenCount() {
        return children.size();
    }
 
    public Child getChildItem(int index) {
        return children.get(index);
    }
}



Child.java

package com.example.checkableexpandablelistview;

public class Child {
    private String userid;
    private String fullname;
    private String username;
    private boolean isChecked;
 
    public Child(String userid, String fullname, String username) {
        this.userid = userid;
        this.fullname = fullname;
        this.username = username;
        this.isChecked = false;
    }
 
    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
    }
 
    public void toggle() {
        this.isChecked = !this.isChecked;
    }
 
    public boolean getChecked() {
        return this.isChecked;
    }
 
    public String getUserid() {
        return userid;
    }
 
    public String getFullname() {
        return fullname;
    }
 
    public String getUsername() {
        return username;
    }
}


MainActivity.java

package com.example.checkableexpandablelistview;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.ExpandableListView;

import com.example.aexpandablelist.R;


public class MainActivity extends Activity {

    ArrayList<Group> groups;
    ExpandableListView listView;
    EListAdapter adapter;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        groups = new ArrayList<Group>();
        getJSONObject();
        listView = (ExpandableListView) findViewById(R.id.listView);
        adapter = new EListAdapter(this, groups);
        listView.setAdapter(adapter);
        listView.setOnChildClickListener(adapter);
    }

    /** 解悉 JSON 字串 */
    private void getJSONObject() {
        String jsonStr = "{'CommunityUsersResult':[{'CommunityUsersList':[{'fullname':'a111','userid':11,'username':'a1'}"
                + ",{'fullname':'b222','userid':12,'username':'b2'}],'id':1,'title':'人事部'},{'CommunityUsersList':[{'fullname':"
                + "'c333','userid':13,'username':'c3'},{'fullname':'d444','userid':14,'username':'d4'},{'fullname':'e555','userid':"
                + "15,'username':'e5'}],'id':2,'title':'開發部'}]}";

        try {
            JSONObject CommunityUsersResultObj = new JSONObject(jsonStr);
            JSONArray groupList = CommunityUsersResultObj.getJSONArray("CommunityUsersResult");

            for (int i = 0; i < groupList.length(); i++) {
                JSONObject groupObj = (JSONObject) groupList.get(i);
                Group group = new Group(groupObj.getString("id"), groupObj.getString("title"));
                JSONArray childrenList = groupObj.getJSONArray("CommunityUsersList");

                for (int j = 0; j < childrenList.length(); j++) {
                    JSONObject childObj = (JSONObject) childrenList.get(j);
                    Child child = new Child(childObj.getString("userid"), childObj.getString("fullname"),
                            childObj.getString("username"));
                    group.addChildrenItem(child);
                }

                groups.add(group);
            }
        } catch (JSONException e) {
            Log.d("allenj", e.toString());
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}




activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ExpandableListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ExpandableListView>

</RelativeLayout>

group_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/tvGroup"
        android:layout_width="280dp"
        android:layout_height="45dip"
        android:gravity="center_vertical|left"
        android:paddingLeft="45dp"
        android:textSize="17dip"
        android:textStyle="bold" >
    </TextView>

    <CheckBox
        android:id="@+id/chbGroup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false" />

</LinearLayout>

child_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/tvChild"
        android:layout_width="280dp"
        android:layout_height="45dip"
        android:gravity="center_vertical"
        android:paddingLeft="45dp"
        android:textSize="17dip"
        android:textStyle="bold" >
    </TextView>

    <CheckBox
        android:id="@+id/chbChild"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:focusable="false" />

</LinearLayout>


你可能感兴趣的:(android,android,checkbox,checkbox)