【Android】扩展BaseExpandableListAdpter实现ExpandableAdapter

news2025/1/14 18:07:14

今天分享如何扩展BaseExpandableListAdpter实现ExpandableAdapter,很简单的一个例子。

效果示例:

 

核心是重写BaseExpandableListAdpter,其中BaseExpandableListAdpter则分成了两部分:组和子列表,要注意的是,重写isChildSelectable()方法需要返回true,不然不会触发 子Item的点击事件!

XML代码分享

主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"
    android:padding="5dp"
    tools:context=".MainActivity">

    <ExpandableListView
        android:id="@+id/exlist_lol"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:childDivider="#E02D2F" />

</RelativeLayout>

父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"
    android:padding="5dp">

    <TextView
        android:id="@+id/tv_group_name"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:gravity="center_vertical"
        android:paddingLeft="30dp"
        android:text="Parent"
        android:textStyle="bold"
        android:textSize="20sp" />

</LinearLayout>

子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"
    android:padding="5dp">

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="15dp"
        android:focusable="false"
        android:text="child"
        android:textSize="18sp" />

    <ImageView
        android:id="@+id/img_icon"
        android:layout_width="38dp"
        android:layout_height="47dp"
        android:layout_alignParentRight="true"
        android:layout_centerInParent="true"
        android:paddingRight="10dp"
        android:src="@drawable/arr_right" />
</LinearLayout>

Activity代码分享

import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ArrayList<Group> gData = null;
    private ArrayList<ArrayList<Item>> iData = null;
    private ArrayList<Item> lData = null;
    private Context mContext;
    private ExpandableListView exlist_lol;
    private MyBaseExpandableListAdapter myAdapter = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        exlist_lol = (ExpandableListView) findViewById(R.id.exlist_lol);


        //数据准备
        gData = new ArrayList<Group>();
        iData = new ArrayList<ArrayList<Item>>();
        gData.add(new Group("Subject"));

        lData = new ArrayList<Item>();

        Resources res =getResources();
        String[] subject=res.getStringArray(R.array.subject);

        for(int i=0;i<subject.length;i++)
        {
            lData.add(new Item(R.drawable.arr_right,subject[i]));  //值得说明的是,这里的数据源于项目中的values/list.xml,同理,一级目录也可以用这样的方式赋值
        }
        iData.add(lData);


        myAdapter = new MyBaseExpandableListAdapter(gData,iData,mContext);
        exlist_lol.setAdapter(myAdapter);


        //为列表设置点击事件
        exlist_lol.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                Toast.makeText(mContext, "你点击了:" + iData.get(groupPosition).get(childPosition).getiName(), Toast.LENGTH_SHORT).show();
                return true;
            }
        });


    }
}

values下的list.xml(Tip:像一般的下拉框Spinner也可以读取xml资源)

<?xml version="1.0" encoding="utf-8"?>
<resources>
      <string-array name="subject">
          <item>Chinese</item>
          <item>Math</item>
          <item>English</item>
          <item>Physics</item>
          <item>Chemistry</item>
           <item>History</item>
      </string-array>
</resources>

Adapter代码分享

package com.example.listmain;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

public class MyBaseExpandableListAdapter extends BaseExpandableListAdapter {

    private ArrayList<Group> gData;
    private ArrayList<ArrayList<Item>> iData;
    private Context mContext;

    public MyBaseExpandableListAdapter(ArrayList<Group> gData, ArrayList<ArrayList<Item>> iData, Context mContext) {
        this.gData = gData;
        this.iData = iData;
        this.mContext = mContext;
    }

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

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

    @Override
    public Group getGroup(int groupPosition) {
        return gData.get(groupPosition);
    }

    @Override
    public Item getChild(int groupPosition, int childPosition) {
        return iData.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) {

        ViewHolderGroup groupHolder;
        if(convertView == null){
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.item_exlist_group, parent, false);
            groupHolder = new ViewHolderGroup();
            groupHolder.tv_group_name = (TextView) convertView.findViewById(R.id.tv_group_name);
            convertView.setTag(groupHolder);
        }else{
            groupHolder = (ViewHolderGroup) convertView.getTag();
        }
        groupHolder.tv_group_name.setText(gData.get(groupPosition).getgName());
        return convertView;
    }

    //取得显示给定分组给定子位置的数据用的视图
    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        ViewHolderItem itemHolder;
        if(convertView == null){
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.item_exlist_item, parent, false);
            itemHolder = new ViewHolderItem();
            itemHolder.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
            itemHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
            convertView.setTag(itemHolder);
        }else{
            itemHolder = (ViewHolderItem) convertView.getTag();
        }
        itemHolder.img_icon.setImageResource(iData.get(groupPosition).get(childPosition).getiId());
        itemHolder.tv_name.setText(iData.get(groupPosition).get(childPosition).getiName());
        return convertView;
    }

    //设置子列表是否可选中
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }


    private static class ViewHolderGroup{
        private TextView tv_group_name;
    }

    private static class ViewHolderItem{
        private ImageView img_icon;
        private TextView tv_name;
    }

}

还有两个类:Item 和 Group


public class Item {

    private int iId;
    private String iName;

    public Item() {
    }

    public Item(int iId, String iName) {
        this.iId = iId;
        this.iName = iName;
    }

    public int getiId() {
        return iId;
    }

    public String getiName() {
        return iName;
    }

    public void setiId(int iId) {
        this.iId = iId;
    }

    public void setiName(String iName) {
        this.iName = iName;
    }
}
public class Group {
    private String gName;

    public Group() {
    }

    public Group(String gName) {
        this.gName = gName;
    }

    public String getgName() {
        return gName;
    }

    public void setgName(String gName) {
        this.gName = gName;
    }
}

补充一下,网上说实现ExpandableAdapter有三种方式:

1. 扩展BaseExpandableListAdpter实现ExpandableAdapter。

2. 使用SimpleExpandableListAdpater将两个List集合包装成ExpandableAdapter

3. 使用simpleCursorTreeAdapter将Cursor中的数据包装成SimpleCuroTreeAdapter 

鉴于我写的Demo比较简单,所以就先用了第一种。后面有时间我也会另外研究一下~

最后,本次练手的代码可以左转到我的主页查看下载资源,欢迎一起交流学习吖~

参考资料:

ExpandableListView使用方法详解_会飞的鱼儿android的博客-CSDN博客_expandablelistview

2.5.5 ExpandableListView(可折叠列表)的基本使用 | 菜鸟教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10599.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA远程debug教程

IDEA远程debug教程 当你在本地开发的时候&#xff0c;你需要调试服务器上的程序时&#xff0c;远程调试就显得非常有用。 JAVA 支持调试功能&#xff0c;本身提供了一个简单的调试工具JDB&#xff0c;支持设置断点及线程级的调试同时&#xff0c;不同的JVM通过接口的协议联系…

【Netty源码系列(二)】解读EventLoopGroup

【Netty源码系列文章中源码出自4.1.84.Final版本】 文章目录1. EventLoopGroup接口类2. NioEventLoopGroup创建过程2.1 Executor实现机制2.2 EventLoop对象创建&#xff08;newChild()方法&#xff09;本篇文章主要看一下 EventLoopGroup的源码&#xff0c;了解一下它的创建过程…

二、react的组件-state-props-setState

目标 理解组件和组件的创建、以及能够根据实际场景去划分合理的组件。理解并且能够灵活的应用组件中的state、props。可以使用组件去实现各种前端交互。 知识点 组件的定义&#xff1a;组件能够表示一块视图的结构表现以及逻辑交互&#xff0c;并且可以重复利用。如何创建组件…

【ROS】机械人开发四--ROS常用概念与Launch文件

机械人开发四--ROS常用概念与Launch文件一、ROS常用概念1.1 ROS 的结构1.2 ROS 话题通信1.3 海龟仿真器 仿真 例程二、Launch文件2.1 功能2.2 文件语法2.3 参数服务器2.4 节点分组与重命名标签一、ROS常用概念 1.1 ROS 的结构 ROS 中有一些很重要的基础概念&#xff1a;节点&…

四、ref与DOM-findDomNode-unmountComponentAtNode

目标 理解react的框架使用中&#xff0c;真实dom存在的意义。 使用真实dom和使用虚拟dom的场景。 灵活掌握并能够合理使用操作真实dom的方法。 知识点 react中提供了ref这个属性来获取原生的dom节点&#xff0c;使用方式&#xff1a;在虚拟dom中添加ref属性&#xff0c;即可…

笔试强训(三十七)

目录一、选择题二、编程题2.1 mkdir2.1.1 题目2.1.2 题解2.2 数据库连接池2.2.1 题目2.2.2 题解一、选择题 &#xff08;1&#xff09;下面关于源端口地址和目的端口地址的描述中&#xff0c;正确的是&#xff08;A&#xff09; A.在TCP/UDP传输段中&#xff0c;源端口地址和目…

从内部失衡到外部失衡-中国视角下的宏观经济

从内部失衡到外部失衡 – 潘登同学的宏观经济学笔记 文章目录从内部失衡到外部失衡 -- 潘登同学的宏观经济学笔记国际金融复习全球失衡与储蓄过剩利用拉姆齐模型进行分析数值模拟外部失衡与国际收支危机国际支付工具的作用资产价格泡沫国际收支危机亚洲金融危机中国在亚洲金融危…

智能家居项目开发准备工作

智能家居代码机构——简单工厂模式&#xff1a; 什么是设计模式&#xff1f;百度百科解释&#xff1a; 软件设计模式&#xff08;Design pattern&#xff09;&#xff0c;又称设计模式&#xff0c;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设…

好心情精神心理平台:精神疾病怎样才算「治好」?医生和患者眼中的标准不一样!

精神疾病恢复到什么程度才算「治好」了&#xff1f; 很多患者朋友认为&#xff0c;症状消失就代表病好了&#xff0c;就可以停药了。 不是我吓唬你&#xff0c;如果你见症状好转就停药&#xff0c;那病情出现反复是必然结果。 实现疾病症状的消除&#xff0c;这只是达到了「临…

[附源码]java毕业设计驾校管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]java毕业设计基于的疫苗预约系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

详解VSCode中C++工程配置

安装MinGW-w64及环境变量配置 下载MinGW-w64 可以通过官网直接进行下载在线安装包&#xff0c;然后在本地进行安装即可&#xff08;但是基本都会由于网络超时等各种原因终止&#xff09;。 因此这里建议直接下载 MinGW-w64 库解压&#xff0c;然后在系统中指定环境变量即可。…

低资源场景下的命名实体识别

Overview 低资源下的命名实体识别主要分为两个方面&#xff0c;一种是in-domain下的N-way-K-shot类型的少样本&#xff0c;一种是cross-domain下现在资源丰富的sourc-domain上进行微调&#xff0c;之后再迁移到低资源的target-domain进一步微调。 基于prompt的方法在少样本分…

C语言学习-数组(4)

目录 思维导图&#xff1a; 1. 一维数组的创建和初始化 1.1 数组的创建 1.2 数组的初始化 1.3 一维数组的使用 1.4 一维数组在内存中的存储 2. 二维数组的创建和初始化 2.1 二维数组的创建 2.2 二维数组的初始化 2.3 二维数组的使用 2.4 二维数组在内存中的存…

C# async / await 的使用方法

目录 一、简介 二、异步等待返回结果 三、异步方法的返回类型 四、await foreach 五、Task.Delay 结束 一、简介 await 运算符暂停对其所属的 async 方法的求值&#xff0c;直到其操作数表示的异步操作完成。 异步操作完成后&#xff0c;await 运算符将返回操作的结果&a…

【Xilinx】Zynq\MPSoc\Versal不同速度等级下的ARM主频

【Xilinx】Zynq\MPSoc\Versal不同速度等级下的ARM主频一、Zynq&#xff08;A9&#xff09;二、MPSoC(A53R5)三、Versal(A72R5F)最近有很多人在选型的时候&#xff0c;问到ARM主频的问题&#xff0c;不知道去哪里找这个参数。 授人以鱼不如授人以渔&#xff0c;基本的通用方法是…

【面试题】 TypeScript 前端面试题 由浅到深

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 基本类型介绍 1.Boolean&#xff0c;Number&#xff0c;String 声明:类型 类型对应变量 let flag:boolean true let …

【现代密码学原理】——哈希函数(学习笔记)

&#x1f4d6; 前言&#xff1a;我们在登录QQ有时会遇到密码忘记的问题&#xff0c;那么思考一下&#xff0c;为什么腾讯公司不直接把密码发还给用户而是要求设置新密码呢。其实&#xff0c;不保存密码&#xff0c;是为了更好地对密码保密&#xff0c;换言之&#xff0c;腾讯的…

力扣(LeetCode)106. 从中序与后序遍历序列构造二叉树(C++)

递归 如图&#xff0c;后序序列按照左右根遍历&#xff0c;所以根在最后。逆着后序遍历的顺序&#xff0c;按照根右左递归建树就可以复原这棵树。后序序列&#xff0c;可以确定根的位置 postrootpostrootpostroot 和根结点的值。我们在中序序列找到根结点的值&#xff0c;就确定…

《深度学习进阶 自然语言处理》第四章:Embedding层和负采样介绍

文章目录4.1 word2vec的改进一4.1.1 Embedding层4.2 word2vec的改进二4.2.1 中间层之后的计算问题4.2.2 从多分类到二分类4.2.3 负采样总结之前文章链接&#xff1a; 开篇介绍&#xff1a;《深度学习进阶 自然语言处理》书籍介绍 第一章&#xff1a;《深度学习进阶 自然语言处…