Android ListView 分组

在 Android 开发中,ListView 是常用的列表视图控件,用于展示大量数据并支持用户的滚动操作。有时候,我们需要将数据根据某个属性进行分组展示,这就需要使用到 ListView 的分组功能。

实现分组功能思路

实现 ListView 的分组功能可以通过以下步骤来完成:

  1. 准备数据:将需要展示的数据按照分组进行分类。
  2. 创建适配器:自定义一个继承自 BaseAdapter 的适配器类,重写必要的方法。
  3. 设置适配器:将适配器设置给 ListView
  4. 自定义分组视图:创建一个分组视图的布局文件,用于显示分组的标题。
  5. 自定义子项视图:创建一个子项视图的布局文件,用于显示每个分组中的子项数据。

示例代码

以下是一个简单的示例代码,展示了如何实现 ListView 的分组功能。

数据准备

List<Map<String, Object>> groupData = new ArrayList<>();
List<List<Map<String, Object>>> childData = new ArrayList<>();

String[] groupTitles = {"Group 1", "Group 2", "Group 3"};
String[][] childTitles = {
    {"Child 1-1", "Child 1-2", "Child 1-3"},
    {"Child 2-1", "Child 2-2"},
    {"Child 3-1", "Child 3-2", "Child 3-3", "Child 3-4"}
};

for (int i = 0; i < groupTitles.length; i++) {
    Map<String, Object> group = new HashMap<>();
    group.put("title", groupTitles[i]);
    groupData.add(group);
  
    List<Map<String, Object>> children = new ArrayList<>();
    for (int j = 0; j < childTitles[i].length; j++) {
        Map<String, Object> child = new HashMap<>();
        child.put("title", childTitles[i][j]);
        children.add(child);
    }
    childData.add(children);
}

创建适配器

public class MyAdapter extends BaseExpandableListAdapter {

    private List<Map<String, Object>> groupData;
    private List<List<Map<String, Object>>> childData;
    private Context context;

    public MyAdapter(Context context, List<Map<String, Object>> groupData, List<List<Map<String, Object>>> childData) {
        this.context = context;
        this.groupData = groupData;
        this.childData = childData;
    }

    @Override
    public int getGroupCount() {
        return groupData.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return childData.get(groupPosition).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groupData.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return childData.get(groupPosition).get(childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.group_item, null);
        }
        TextView titleTextView = view.findViewById(R.id.group_title);
        titleTextView.setText(groupData.get(groupPosition).get("title").toString());
        return view;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.child_item, null);
        }
        TextView titleTextView = view.findViewById(R.id.child_title);
        titleTextView.setText(childData.get(groupPosition).get(childPosition).get("title").toString());
        return view;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
}

设置适配器

ListView listView = findViewById(R.id.listView);
MyAdapter adapter = new MyAdapter(this, groupData, childData);
listView.setAdapter(adapter);

自定义分组视图布局

创建一个名为 group_item.xml 的布局文件,用于显示分组的标题。

<LinearLayout