Android学习之ExpandableListView

article/2025/9/26 15:40:57

什么是ExpandableListView

ExpandableListView是扩展的ListView,继承自ListView;ExpandableListView可以实现点击展开列表,再点击收缩回去的效果。

ExpandableListView的使用

首先需要在主布局文件中声明ExpandableListView;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".TestActivity3"android:orientation="vertical"><!--indicatorLeft:指示符的左边界indicatorRight: 指示符的右边界groupIndicator:设置指示符--><ExpandableListViewandroid:id="@+id/id_elv1"android:layout_width="match_parent"android:layout_height="wrap_content"android:groupIndicator="@drawable/group_indicator"android:indicatorRight="40dp"android:indicatorLeft="10dp"/></LinearLayout>

group_indicator.xml文件,指定不同状态下的样式

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><!--展开状态--><item android:drawable="@drawable/indicator_expand" android:state_expanded="true">true</item><!--非展开状态--><item android:drawable="@drawable/indicator_collapse"></item>
</selector>

新建Chapter类和ChapterItem类;Chapter代表分组,ChapterItem代表分组中的子选项;

public class Chapter {private int id;private String name;//存储分组中的的子选项private List<ChapterItem> chapterItemList = new ArrayList<>();public Chapter() {}public Chapter(int id, String name) {this.id = id;this.name = name;}//向分组中添加子选项public void addChapterItem(ChapterItem chapterItem) {chapterItem.setPid(getId());chapterItemList.add(chapterItem);}//向分组中添加子选项public void addChapterItem(int cid, String cname) {ChapterItem chapterItem = new ChapterItem(cid, cname);chapterItem.setPid(getId());}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<ChapterItem> getChapterItemList() {return chapterItemList;}public void setChapterItemList(List<ChapterItem> chapterItemList) {this.chapterItemList = chapterItemList;}}

ChapterItem类


public class ChapterItem {private String name;//子选项的idprivate int id;//子选项所在分组的idprivate int pid;public ChapterItem() {}public ChapterItem(int id, String name) {this.id = id;this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getPid() {return pid;}public void setPid(int pid) {this.pid = pid;}
}

ChapterLab类,使用此类模拟添加数据


public class ChapterLab {public static List<Chapter> getGenerateMockDats() {List<Chapter> datas = new ArrayList<>();Chapter root1 = new Chapter(1, "Android");Chapter root2 = new Chapter(1, "Java");Chapter root3 = new Chapter(1, "C/C++");Chapter root4 = new Chapter(1, "Python");root1.addChapterItem(new ChapterItem(1,"EventBus"));root1.addChapterItem(new ChapterItem(2, "GreenDao"));root1.addChapterItem(new ChapterItem(3, "Gridle"));root1.addChapterItem(new ChapterItem(4, "Spinner"));root2.addChapterItem(new ChapterItem(5,"spring"));root2.addChapterItem(new ChapterItem(6, "springmvc"));root2.addChapterItem(new ChapterItem(7, "mybatis"));root3.addChapterItem(new ChapterItem(8, "hibernate"));root3.addChapterItem(new ChapterItem(9,"STL"));root3.addChapterItem(new ChapterItem(10, "IO"));root3.addChapterItem(new ChapterItem(11, "指针"));root3.addChapterItem(new ChapterItem(12, "结构体"));root4.addChapterItem(new ChapterItem(13,"爬虫"));root4.addChapterItem(new ChapterItem(14, "数据分析"));root4.addChapterItem(new ChapterItem(15, "AI"));root4.addChapterItem(new ChapterItem(16, "人工智能"));datas.add(root1);datas.add(root2);datas.add(root3);datas.add(root4);return datas;}
}

item_parent_chapter.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="56dp"android:background="#86b2f9"><TextViewandroid:id="@+id/id_tv_parent"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:text="Android"android:textSize="24dp"android:textStyle="bold"/></LinearLayout>

item_child_layoutu.xml文件,子选项布局文件

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="40dp"android:layout_gravity="center_vertical"android:textSize="16dp"android:id="@+id/tv_item"></TextView>

ChapterAdapter数据适配类,这个类继承了BaseExpandableListAdapter并重写了方法,

public class ChapterAdapter extends BaseExpandableListAdapter {//分组的数据private List<Chapter> datas;private LayoutInflater inflater;private Context mContext;public ChapterAdapter(Context context, List<Chapter> datas) {this.datas = datas;this.mContext = context;inflater = LayoutInflater.from(context);}/*** 获取分组的个数* @return*/@Overridepublic int getGroupCount() {return datas.size();}/*** 获取指定分组中子选项的个数* @param groupPosition* @return*/@Overridepublic int getChildrenCount(int groupPosition) {return datas.get(groupPosition).getChapterItemList().size();}/*** 获取指定分组的数据* @param groupPosition* @return*/@Overridepublic Object getGroup(int groupPosition) {return datas.get(groupPosition);}/*** 获取指定分组中的子选项的数据* @param groupPosition* @param childPosition* @return*/@Overridepublic Object getChild(int groupPosition, int childPosition) {return datas.get(groupPosition).getChapterItemList().get(childPosition);}/*** 获取指定分组的ID,这个ID必须是唯一的,可以使用分组的position* @param groupPosition* @return*/@Overridepublic long getGroupId(int groupPosition) {return groupPosition;}/*** 获取子选项的ID,这个ID必须是唯一的,不能使用子条目的position* @param groupPosition* @param childPosition* @return*/@Overridepublic long getChildId(int groupPosition, int childPosition) {return childPosition;}/*** 分组和子选项是否持有稳定的ID,就是说底层数据的改变会不会影响到它们* @return*/@Overridepublic boolean hasStableIds() {return false;}/*** 获取显示指定分组的视图* @param groupPosition* @param isExpanded* @param convertView* @param parent* @return*/@Overridepublic View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {ParentViewHolder parentViewHolder = null;if (convertView == null) {convertView = inflater.inflate(R.layout.item_parent_chapter, parent, false);parentViewHolder = new ParentViewHolder();parentViewHolder.tvName = convertView.findViewById(R.id.id_tv_parent);         convertView.setTag(parentViewHolder);} else {parentViewHolder = (ParentViewHolder) convertView.getTag();}Chapter chapter = datas.get(groupPosition);parentViewHolder.tvName.setText(chapter.getName());return convertView;}/*** 获取指定分组中的指定子选项的视图* @param groupPosition* @param childPosition* @param isLastChild* @param convertView* @param parent* @return*/@Overridepublic View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {ChildViewHolder childViewHolder = null;if (convertView == null) {convertView = inflater.inflate(R.layout.item_child_layout, parent, false);childViewHolder = new ChildViewHolder();childViewHolder.tvName = convertView.findViewById(R.id.tv_item);convertView.setTag(childViewHolder);} else {childViewHolder = (ChildViewHolder) convertView.getTag();}ChapterItem chapterItem = datas.get(groupPosition).getChapterItemList().get(childPosition);childViewHolder.tvName.setText(chapterItem.getName());return convertView;}/*** 指定位置上的子元素是否可选中,返回true才会相应点击事件* @param groupPosition* @param childPosition* @return*/@Overridepublic boolean isChildSelectable(int groupPosition, int childPosition) {return true;}public static class ParentViewHolder {TextView tvName;  }public static class ChildViewHolder {TextView tvName;}
}

主Activity类

public class TestActivity3 extends AppCompatActivity {private ExpandableListView expandableListView;private ChapterAdapter chapterAdapter;private List<Chapter> dataList;private static final String TAG = "TestActivity3";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_test3);initViews();initEvents();}public void initViews() {expandableListView = findViewById(R.id.id_elv1);dataList = ChapterLab.getGenerateMockDats();chapterAdapter = new ChapterAdapter(this,dataList);expandableListView.setAdapter(chapterAdapter);}public void initEvents() {//设置子选项被点击监听事件expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {@Overridepublic boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {Log.d(TAG, "onChildClick: " + groupPosition + " " + childPosition + " " + id);return false;}});//设置分组选项被点击监听事件expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {@Overridepublic boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {Log.d(TAG, "onGroupClick: " + groupPosition + " " + id);return false;}});//设置折叠时的监听事件expandableListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {@Overridepublic void onGroupCollapse(int groupPosition) {Log.d(TAG, "onGroupCollapse: " + groupPosition);}});//设置展开时的监听事件expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {@Overridepublic void onGroupExpand(int groupPosition) {Log.d(TAG, "onGroupExpand: " + groupPosition);}});}}

运行后的效果:
在这里插入图片描述

ExpandableListView自带的指示器的效果不好,所以更多情况下我们会选择自定义一个指示器。
修改item_parent_chapter.xml文件,添加一个ImageView控件作为指示符

<?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="56dp"android:background="#86b2f9"><ImageViewandroid:id="@+id/id_iv_indicator"android:layout_width="24dp"android:layout_gravity="center_vertical"android:layout_marginRight="4dp"android:background="@drawable/group_indicator"android:layout_height="24dp"/><TextViewandroid:id="@+id/id_tv_parent"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:text="Android"android:textSize="24dp"android:textStyle="bold"/></LinearLayout>

修改主界面布局文件中ExpandableListView的android:groupIndicator属性为@null

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".TestActivity3"android:orientation="vertical"><!--indicatorLeft: 指示符的左边约束距离indicatorRight:指示符的右边约束距离groupIndicator:设置指示--><ExpandableListViewandroid:id="@+id/id_elv1"android:layout_width="match_parent"android:layout_height="wrap_content"android:groupIndicator="@null"android:indicatorRight="40dp"android:indicatorLeft="10dp"/></LinearLayout>

修改group_indicator.xml文件为

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><!--当使用ImageView来代替indicator时,使用这个--><item android:drawable="@drawable/indicator_expand" android:state_selected="true">true</item><!--非展开状态--><item android:drawable="@drawable/indicator_collapse"></item>
</selector>

修改ChapterAdapter类中的中的getGroupView方法和ParentViewHolder类为以下所示的样子,

@Overridepublic View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {ParentViewHolder parentViewHolder = null;if (convertView == null) {convertView = inflater.inflate(R.layout.item_parent_chapter, parent, false);parentViewHolder = new ParentViewHolder();parentViewHolder.tvName = convertView.findViewById(R.id.id_tv_parent);parentViewHolder.imageView = convertView.findViewById(R.id.id_iv_indicator);convertView.setTag(parentViewHolder);} else {parentViewHolder = (ParentViewHolder) convertView.getTag();}Chapter chapter = datas.get(groupPosition);parentViewHolder.tvName.setText(chapter.getName());parentViewHolder.imageView.setSelected(isExpanded);return convertView;}java
    public static class ParentViewHolder {TextView tvName;ImageView imageView;}

运行后效果如图:
在这里插入图片描述


http://chatgpt.dhexx.cn/article/7P2Z8LKx.shtml

相关文章

ExpandableListView详解

文章目录 效果图ExpandableListView的简介与使用去掉ExpandableListView的箭头以及自定义Indicator解决setOnChildClickListener失效问题解决collapseGroup(i)崩溃问题解决group_item.xml中包含CheckBox、EditText等&#xff0c;点击不能展开的问题 1.效果图 2.ExpandableLi…

values_list()

转载&#xff1a;https://www.cnblogs.com/chenchao1990/p/5311531.html?utm_sourcetuicool&utm_mediumreferral

列表(lists)

Lists and the things you can do with them.Includes indexing(索引&#xff09;,slicing &#xff08;切片&#xff09;and mutating&#xff08;变异&#xff09;. 1.Python 中的列表表示有序的值序列。 以下是如何创建它们的示例&#xff1a; primes [2,3,5,7] #我们可以…

Android Preference API 用法--ListPreference(一)

一&#xff0e;ListPreference简介 我们都只知道SharedPreference非常适合于参数设置功能&#xff0c;在此处的preference 也是代表SharedPreference的意思&#xff0c;在SharedPreference中&#xff0c;我们可以迅速的将某些值保存进xml文件中&#xff0c;然后我们可以读取这…

android entries属性,ListPreference需要设置两个属性:android:entries和android:entryValues...

android:defaultValue"black" android:entries"array/setting_skintheme" android:entryValues"array/setting_skintheme_value" android:key"SkinTheme" android:summary"请选择您喜欢的软件皮肤颜色" android:title"…

Android ListPreference的用法

首先&#xff0c;我们明确&#xff0c;preference是和数据存储相关的。 其次&#xff0c;它能帮助我们方便的进行数据存储&#xff01;为什么这个地方一定要强调下方便的这个词呢&#xff1f;原因是&#xff0c;我们可以根本就不使用&#xff0c;我们有另外的N种办法可以实现同…

List总结

ArrayList与LinkedList的区别是什么&#xff1f; 从继承树&#xff0c;底层数据结构&#xff0c;线程安全&#xff0c;执行效率来进行分析。 1.底层使用的数据结构 ArrayList 底层使用的是Object数组&#xff0c;初始化时就会指向的会是一个static修饰的空数组&#xff0c;数…

android Preference ListPreference EditTextPreference

android中包含Preference ListPreference EditTextPreference等控件布局的写法&#xff0c;已经操作各个控件的事件介绍&#xff0c;如下 <?xml version"1.0" encoding"utf-8"?> <PreferenceScreen xmlns:android"http://schemas.android…

Android中ListPreference的使用

这篇主要是具体例子&#xff0c;可以先看一下理论&#xff0c;网址是&#xff1a;Android中Preference的使用以及监听事件分析 我们可以先看一下效果图 我们先截取不小段布局&#xff0c;代码如下&#xff1a; <ListPreferenceandroid:defaultValue"string/usb_defaul…

list列表的用法

List&#xff08;列表&#xff09;是 Python中使用最频繁的数据类型。列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同&#xff0c;它支持数字&#xff0c;字符串甚至可以包含列表&#xff08;所谓嵌套&#xff09;。列表是写在方括号 [ ] 之间&#xff0…

List 列表的用法

List&#xff08;列表&#xff09; 是 Python 中使用最频繁的数据类型。列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同&#xff0c;它支持数字&#xff0c;字符串甚至可以包含列表&#xff08;所谓嵌套&#xff09;。列表是写在方括号 [ ] 之间、用逗号…

自定义ListPreference弹出Dialog背景

公司最近项目需求是用实体键来在应用内操作,这就需要对那些可点击的widget的背景进行自定义,使其响应focus状态随即变化。大部分的layout改动都是挺简单的。 但是遇到一个主要的问题就是自带的PreferenceFragment,里面的layout不是通过平时常用的Button ImageView那些来写的…

android之ListPreference的用法_PreferenceActivity用法

首先&#xff0c;我们明确&#xff0c;preference是和数据存储相关的。 其次&#xff0c;它能帮助我们方便的进行数据存储&#xff01;为什么这个地方一定要强调下方便的这个词呢&#xff1f;原因是&#xff0c;我们可以根本就不使用&#xff0c;我们有另外的N种办法可…

ListPreference详解与使用

listprefenence比switchpreference多了一个arrays.xml&#xff0c;这个arrays.xml就是用来写我们需要的list的内容。 以切换mode功能为例&#xff0c;就是切换协议的mode&#xff0c;一共需要五个选项。除了switchpreference中的key&#xff0c;title&#xff0c;summary和pers…

互联网协议 — TCP — 流量控制

目录 文章目录 目录TCP 流量控制流量控制处理流程 TCP 流量控制 TCP 流量控制由滑动窗口&#xff08;Sliding Window&#xff09;技术支撑。Sender 根据 Receiver 返回 ACK 中包含的 Window Size 字段来动态调整自身发送 Segments 的速率&#xff0c;以此保证收发双方不会因为…

电信网络性能质量测量

电信网络性能质量测量 作者:千里孤行(http://blog.csdn.net/yanghehong) 为什么要有质量和性能的测量 • 验证系统架构,配置 • 定位已有问题 • 及早发现潜在问题 • 为系统架构演进提供数据支持 服务质量的四个视角 服务质量的网络部分和非网络部分 从网络角度出发, QoS…

网络性能指标简介

网络性能指标简介 1. 网络容量&#xff08;Network Capacity&#xff0c;NC&#xff09; 网络容量是描述无线网络性能的最重要的指标之一&#xff0c;该指标使得人们在给定无线信道的基本容量限制的条件下&#xff0c;能够确定一些应用在理论上是否可行。网络容量通常指理论上…

基于神经网络的天气质量指数预测

基于神经网络的空气质量指数预测 1 项目背景 1.1背景 随着我国经济的快速发展&#xff0c;大量的工厂企业以及尾气排放使得大气环境污染日益严重&#xff0c;所以大气污染的预测防治工作应该加大力度[1]。通过预测未来影响空气质量指数的污染物浓度&#xff0c;实现我们对短…

腾讯海外轻量服务网络质量下降原因和解决方法

腾讯海外轻量服务网络质量下降原因和解决方法 腾讯海外轻量服务网络质量下降原因和解决方法问题背景问题原因影响这个问题是否会自动解决呢?解决方案有吗?方案一: GAME加速.方案二: 使用优质带宽的中转服务器方案三: 让你的服务器提供方帮你一站式解决问题 腾讯海外轻量服务网…

NQA网络质量分析

NQA网络质量分析&#xff0c;是一种实时的网络性能探测和统计技术&#xff0c;可以对响应时间、网络抖动、丢包率等网络信息进行统计NQA能实时监视网络QOS&#xff0c;在网络发生故障时有效的诊断和定位。&#xff08;和BFD不同&#xff0c;BFD像侦测兵报告错误&#xff0c;NQA…