使用ExpandableListView实现列表分组

        当你需要在Android应用中展示大量数据时,列表是一个常见的UI组件。但是,有时候数据量大到一定程度,简单的列表就无法满足需求。这时,分组列表就成为了一个很好的选择。ExpandableListView 是 Android 中的一个强大的组件,它可以帮助你轻松地实现列表分组的功能。在这篇博客中,我们将探讨如何使用 ExpandableListView 来实现列表的分组功能,让你的应用更加高效和易于管理。我们将深入讨论 ExpandableListView 的基本用法、如何为列表添加分组、以及如何自定义列表项的外观和交互效果。通过本文的学习,你将能够掌握使用 ExpandableListView 构建分组列表的技巧,为你的应用增添更多交互和可用性。

        先看效果图:

        (可能UI有点拉哈哈哈😂,但是不影响功能实现)

        

        

        那么这种效果是如何实现的,其实代码也是比较简单,其中数据部分根据自己需求进行更改。

        直接看代码:

        MainActivity.java(查询数据部分可以根据需求进行更改例如进行网络获取)

public class MainActivity extends AppCompatActivity {


    private List<Data> datalist = new ArrayList<>();

    private HashMap<String, List<Data>> postMap = new HashMap<>();
    private ExpandableListView expandableListView;
    private ParentAdapter expandableListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        expandableListView=findViewById(R.id.expandableListView);

        querydata();//查询数据
    }
    /**
     * 模拟网络查询数据
     */
    private void querydata(){

        datalist.add(new Data("中国", "四川"));
        datalist.add(new Data("中国", "河南"));
        datalist.add(new Data("中国", "广东"));
        datalist.add(new Data("中国", "浙江"));
        datalist.add(new Data("美国", "纽约"));
        datalist.add(new Data("美国", "加利福尼亚"));
        datalist.add(new Data("美国", "德克萨斯"));
        datalist.add(new Data("英国", "伦敦"));
        datalist.add(new Data("英国", "曼彻斯特"));
        datalist.add(new Data("法国", "巴黎"));
        groups();
    }
    /**
     * 数据分组
     * 根据 category 分组
     */
    private void groups(){
        for (Data data : datalist) {
            String category = data.getCategory();
            // 如果 postMap 中不包含该 category,则新建一个 List
            // 否则,获取已存在的 List
            List<Data> categoryList = postMap.computeIfAbsent(category, k -> new ArrayList<>());

            // 将当前的 Data 对象添加到 category 对应的 List 中
            categoryList.add(data);
            // 初始化适配器
            expandableListAdapter = new ParentAdapter(MainActivity.this, postMap);
            // 设置 ExpandableListView 的适配器
            expandableListView.setAdapter(expandableListAdapter);
        }
    }
}

        activity_main.xml(主布局)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ExpandableListView
        android:id="@+id/expandableListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:groupIndicator="@null"/>

</androidx.constraintlayout.widget.ConstraintLayout>

        ParentAdapter.java

public class ParentAdapter implements ExpandableListAdapter {

    private Context context;
    private HashMap<String, List<Data>> postMap;
    private final List<String> categories;
    
    public ParentAdapter(Context context, HashMap<String, List<Data>> postMap) {
        this.context = context;
        this.postMap = postMap;
        this.categories = new ArrayList<>(postMap.keySet());
    }
    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
    }
    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
    }
    @Override
    public int getGroupCount() {
        return categories.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return 1;
    }

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

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return categories.get(groupPosition);
    }
    @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) {

        ParentHolder parentHolder = null;
        String category = (String) getGroup(groupPosition);

        if(convertView == null) {
            LayoutInflater userInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
            convertView = userInflater.inflate(R.layout.item_parent, null);
            convertView.setHorizontalScrollBarEnabled(true);

            parentHolder = new ParentHolder();
            convertView.setTag(parentHolder);

        } else {
            parentHolder = (ParentHolder) convertView.getTag();
        }
        parentHolder.category = (TextView) convertView.findViewById(R.id.category);
        parentHolder.category.setText(category);
        
        return convertView;
    }
    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        String category=categories.get(groupPosition);
        //String category = (String) getGroup(groupPosition);
        ChildHolder childHolder = null;
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.item_group_child, parent, false);
            childHolder = new ChildHolder();
            convertView.setTag(childHolder);
        }
        else {
            childHolder = (ChildHolder) convertView.getTag();
        }
        childHolder.horizontalListView = (RecyclerView) convertView.findViewById(R.id.recycreyView);
        // 设置 RecyclerView 的布局管理器和适配器
        LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
        childHolder.horizontalListView.setLayoutManager(layoutManager);

        ChildAdapter horizontalListAdapter = new ChildAdapter(context, postMap.get(category));
        childHolder.horizontalListView.setAdapter(horizontalListAdapter);

        return convertView;
    }
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }
    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }
    @Override
    public boolean isEmpty() {
        return false;
    }
    @Override
    public void onGroupExpanded(int groupPosition) {
    }
    @Override
    public void onGroupCollapsed(int groupPosition) {
    }
    @Override
    public long getCombinedChildId(long groupId, long childId) {
        return 0;
    }

    @Override
    public long getCombinedGroupId(long groupId) {
        return 0;
    }

    private static class ChildHolder {
        static RecyclerView horizontalListView;
    }
    private static class ParentHolder {
        TextView category;
    }
}

        item_parent.xml(父视图)

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

    <TextView
        android:id="@+id/category"
        android:textSize="18dp"
        android:text="Text"
        android:layout_weight="1"
        android:gravity="center|left"
        android:paddingLeft="10dp"
        android:background="#FA7298"
        android:textColor="@color/white"
        android:layout_width="wrap_content"
        android:layout_height="50dp" />
    
</LinearLayout>

        item_group_child.xml(这个就是子视图的容器,也可以使用ListView,使用RecyclerView可以实现更多布局展现方例如线性、瀑布流等)

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recycreyView"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"/>

        ChildAdapter.java(子视图RecyclerView的适配器)                

public class ChildAdapter extends RecyclerView.Adapter<ChildAdapter.ViewHolder> {

    private Context context;
    private List<Data> mobiles;

    public ChildAdapter(Context context, List<Data> mobiles) {
        this.context = context;
        this.mobiles = mobiles;
    }
    static class ViewHolder extends RecyclerView.ViewHolder{

        TextView content;
        
        public ViewHolder(View view){
            super(view);
            content=view.findViewById(R.id.content);
        }
    }
    @NonNull
    @Override
    public ChildAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_child, parent, false);
        context = parent.getContext();
        return new ChildAdapter.ViewHolder(view);
    }
    @SuppressLint("RecyclerView")
    @Override
    public void onBindViewHolder(@NonNull ChildAdapter.ViewHolder holder, int position) {

        Data post = mobiles.get(position);
        holder.content.setText(post.getContent());
        holder.content.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, "你点击了"+post.getContent(), Toast.LENGTH_SHORT).show();
            }
        });
    }
    @Override
    public int getItemCount() {
        return mobiles.size();
    }
}

        item_child.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="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/content"
        android:textSize="18dp"
        android:text="Text"
        android:layout_weight="1"
        android:gravity="center|left"
        android:paddingLeft="10dp"
        android:textColor="@color/black"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:clickable="true"
        android:background="?android:attr/selectableItemBackground"/>

</LinearLayout>

最后别忘了Data.java

public class Data {
    
    private String category;//标签分组

    private String content;//内容

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Data(String category, String content) {
        this.category = category;
        this.content = content;
    }
}

        好了代码基本就是以上这些了,可能给人第一眼感觉有点复杂,其实当你在使用ExpandableListView的时候,你就会发现其实很简单就像一个RecclerView再嵌套一个RecyclerView(我也不知道这个比喻恰当不😂😂),而且分组列表在Android开发应用还是比较多的,我就不一一举例了。

        有任何问题欢迎在评论区指正。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大菠萝‍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值