什么是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;}

运行后效果如图:

Android学习之ExpandableListView相关推荐

  1. android 学习之ExpandableListView

    ExpandableListView是ListView的子类,他在ListView的基础上进行了扩展,它可以将列表项分为几组....以下就是我的一些代码 package com.hurui.myexp ...

  2. 《Android学习指南》目录

    转自:http://android.yaohuiji.com/about Android学习指南的内容分类: 分类 描述 0.学习Android必备的Java基础知识 没有Java基础的朋友,请不要先 ...

  3. Android:Android学习路线图

    https://blog.csdn.net/libing1991_/article/details/53455243 前言 工作快一年,Android完全靠自学,看着那些基础教程一步步去做,写过简单的 ...

  4. Android微信通讯录界面代码,Android中使用Expandablelistview实现微信通讯录界面

    之前的博文<Android 中使用ExpandableListView 实现分组的实例>我简单介绍了使用ExpandableListView实现简单的好友分组功能,今天我们针对之前的所做的 ...

  5. Android学习资源汇总

    镇楼:Android官方培训课程中文版 学习网址 Android官网API,文档,开发,资讯 玩Android–鸿洋名下 trinea segmentfault头条 Google Android De ...

  6. Android学习路线

    Android学习路线 第一阶段:Java面向对象编程 1.Java基本数据类型与表达式,分支循环.  2.String和StringBuffer的使用.正则表达式.  3.面向对象的抽象,封装,继承 ...

  7. 一篇文章一张思维导图看懂Android学习最佳路线

    一篇文章一张思维导图看懂Android学习最佳路线 先上一张android开发知识点学习路线图思维导图 Android学习路线从4个阶段来对Android的学习过程做一个全面的分析:Android初级 ...

  8. Android学习系列(10)--App列表之拖拽ListView(上)

    研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨.       鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. ...

  9. Android学习第一书

    大家好,我是一名Facebook的工程师,同时也是<第一行代码--Android>的忠实读者. 虽然我最近几年是在国外读书和工作的,但是和很多人一样,我也非常喜欢郭霖的博客以及他写的< ...

  10. Android学习笔记21:ImageView获取网络图片

    Android平台有3种网络接口可以使用,它们分别是:java.net.*(标准java接口).org.apache(Apache接口)和android.net.*(Android网络接口).本文将使 ...

最新文章

  1. 谷歌新研究:基于数据共享的神经网络快速训练方法
  2. linux文件管理相关操作
  3. java课程设计题目及代码中国象棋,写的太详细了
  4. wxWidgets:wxCustomBackgroundWindow<W> 类模板用法
  5. Caused by: android.os.NetworkOnMainThreadException错误解决办法
  6. mysql_install_db创建空库_MySQL数据库的初始化mysql_install_db
  7. Redis学习总结(6)——Redis 高级特性与案例学习
  8. Linux下的压缩和解压缩命令——compress/uncompress
  9. BadBoy+JMeter应用过程中遇到的问题汇总
  10. 项目经理案头手册学习系列【9、10】——资源强制进度计划、应用PERT编制进度计划...
  11. 解决mescroll固定位置上拉加载无效果?真的只需一步
  12. C语言实现操作系统简单的P V操作
  13. 基金21年发展极简史
  14. Matlab-四杆桁架结构的有限元分析(有限元分析基础-曾攀)
  15. Windows 98光盘启动安装过程详细图解
  16. 2015年第六届蓝桥杯B组(C/C++)预赛题目及个人答案
  17. hardware - cortex-A15, cortex-A35,cortex-A53,cortex-A72
  18. 墨天轮国产数据库沙龙 | 四维纵横姚延栋 :MatrixDB,All-in-One高性能时序数据库
  19. 微软免费杀毒软件Morro即将发布
  20. 图论及其应用 2010年期末考试 答案 总结

热门文章

  1. MySQL在线DDL gh-ost使用说明
  2. 串口通信协议之SPI通信协议
  3. url转码解码工具类
  4. igbt原理动画演示视频_igbt的结构原理与特性图解
  5. Matlab如何多行添加注释和取消注释
  6. 2022道路运输企业安全生产管理人员考试模拟100题及在线模拟考试
  7. 基于Pytorch的YoLoV4模型代码及作品欣赏
  8. ntp服务restrict_ntp服务器配置问题
  9. r语言结构方程模型可视化_混合线性模型——R语言
  10. java snakeyaml_SnakeYaml快速入门和使用