由于工作需要,今天简单研究了一下ExpandableListView,做了一个类似QQ列表的Demo,和大家分享一下。
效果图如下:

先来看看主布局文件:

<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:background="#EDEDED"tools:context="com.example.expandablelistview.MainActivity" ><ExpandableListView
        android:id="@+id/my_listview"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="8dp"android:layout_marginRight="8dp"android:layout_marginTop="10dp"android:divider="@null"android:dividerHeight="8dip" ></ExpandableListView></RelativeLayout>

这里我们不使用系统默认的分隔线,两个组之间的距离为8dp.

对于ExpandableListView,系统为我们提供了专门的适配器BaseExpandableListAdapter,我们可以自定义一个适配器继承BaseExpandableListAdapter,实现该类中的一些方法即可。
代码如下:

public class MyAdapter extends BaseExpandableListAdapter {private List<GroupBean> list;private Context context;public MyAdapter(List<GroupBean> list, Context context) {this.list = list;this.context = context;}public MyAdapter() {}@Overridepublic int getGroupCount() {return list.size();}@Overridepublic int getChildrenCount(int groupPosition) {return list.get(groupPosition).getChildren().size();}@Overridepublic Object getGroup(int groupPosition) {return list.get(groupPosition);}@Overridepublic Object getChild(int groupPosition, int childPosition) {return list.get(groupPosition).getChildren().get(childPosition);}@Overridepublic long getGroupId(int groupPosition) {return groupPosition;}@Overridepublic long getChildId(int groupPosition, int childPosition) {return childPosition;}@Overridepublic boolean hasStableIds() {return false;}@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {GroupHolder holder;if (convertView == null) {holder = new GroupHolder();convertView = LayoutInflater.from(context).inflate(R.layout.item_group, null);holder.title = (TextView) convertView.findViewById(R.id.group_title);holder.iv = (ImageView) convertView.findViewById(R.id.group_ico);convertView.setTag(holder);} else {holder = (GroupHolder) convertView.getTag();}holder.title.setText(list.get(groupPosition).getGroupName());if (isExpanded) {holder.iv.setImageResource(R.drawable.rounds_open);} else {holder.iv.setImageResource(R.drawable.rounds_close);}return convertView;}@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {ChildHolder holder;if (convertView == null) {holder = new ChildHolder();convertView = LayoutInflater.from(context).inflate(R.layout.item_child, null);holder.name = (TextView) convertView.findViewById(R.id.child_name);holder.sign = (TextView) convertView.findViewById(R.id.child_sign);convertView.setTag(holder);} else {holder = (ChildHolder) convertView.getTag();}ChildBean cb = list.get(groupPosition).getChildren().get(childPosition);holder.name.setText(cb.getName());holder.sign.setText("[签名]"+cb.getSign());return convertView;}@Overridepublic boolean isChildSelectable(int groupPosition, int childPosition) {return false;}class GroupHolder {TextView title;ImageView iv;}class ChildHolder {TextView name, sign;}
}

这里的代码有点长,我们稍微解释一下,先是构造方法中传入两个参数,一个是数据源list,另外一个是上下文,list是一个GroupBean集合,GroupBean如下:

public class GroupBean {private String groupName;private List<ChildBean> children;public String getGroupName() {return groupName;}public void setGroupName(String groupName) {this.groupName = groupName;}public List<ChildBean> getChildren() {return children;}public void setChildren(List<ChildBean> children) {this.children = children;}public GroupBean(String groupName, List<ChildBean> children) {this.groupName = groupName;this.children = children;}public GroupBean() {}}

很明显,GroupBean有两个属性,一个是组名字,另外一个是该组下子项的一个集合,这个ChildBean就是每个组下面的每一个对象的数据,ChildBean代码如下:

public class ChildBean {private String name;private String sign;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSign() {return sign;}public void setSign(String sign) {this.sign = sign;}public ChildBean(String name, String sign) {this.name = name;this.sign = sign;}public ChildBean() {}}

说完list,下面就是getGroupCount()和getChildrenCount(),这个有点类似于我们使用BaseAdapter时的getCount(),不同的是这里分别要返回每个组的数量,以及组内成员的数量,那么组的数量当然就是list.size(),组内成员的数量由于每组不同,所以要先拿到每个组,再拿到该组里成员的数量,代码就是list.get(groupPosition).getChildren().size();。接下来的两个方法就是getGroup()和getChild(),这个类似于BaseAdapter中的getItem,我们返回的时候还是组和组内的子项分开返回,代码很简单,就不多说了。稍微长一点的方法就是getGroupView和getChildView,不多也都没啥逻辑,和我们在ListView中使用BaseAdapter中的getView方法差不多,不同的是数据赋值的时候有差别。

我个人觉得,使用ExpandableListView关键在于把数据结构搞清楚,Group和Child搞清楚了,其他的都很简单。

这里我把Group的布局和Child的布局贴出来给大家看看:

item_group.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="48dp"android:background="@drawable/item_background_select" ><TextView
        android:id="@+id/group_title"android:layout_width="wrap_content"android:layout_height="48dp"android:layout_marginLeft="36dp"android:gravity="center"android:text="好友分组"android:textSize="18sp" /><ImageView
        android:id="@+id/group_ico"android:layout_width="24dip"android:layout_height="24dip"android:layout_alignParentRight="true"android:layout_marginBottom="12dp"android:layout_marginLeft="24dp"android:layout_marginRight="24dp"android:layout_marginTop="12dp"android:scaleType="centerInside"android:src="@drawable/rounds_close" /><TextView
        android:id="@+id/split_lines"android:layout_width="1dip"android:layout_height="48dp"android:layout_toLeftOf="@id/group_ico"android:background="#E6E6E6" /></RelativeLayout>

item_child.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="36dp"android:orientation="vertical" ><TextView
        android:id="@+id/child_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="10dip"android:text="姓名"android:textSize="18sp" /><TextView
        android:id="@+id/child_sign"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/child_name"android:paddingLeft="10dip"android:paddingRight="10dip"android:text="签名"android:textSize="12sp" /><View
        android:layout_width="match_parent"android:layout_height="1dp"android:background="#B2DFEE" /></RelativeLayout>

这里还涉及到一个圆角方框,代码是这样的:
item_background_select.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><corners android:radius="8dip" /><solid android:color="#FFFFFFFF" /></shape>

好了,所有的准备工作都已经完成,下面看看怎么使用

public class MainActivity extends Activity {private ExpandableListView mListView;private MyAdapter adapter;private List<GroupBean> list;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//初始化数据initData();mListView = (ExpandableListView) this.findViewById(R.id.my_listview);adapter = new MyAdapter(list, this);mListView.setAdapter(adapter);mListView.setGroupIndicator(null);
//      mListView.expandGroup(0);}private void initData() {list = new ArrayList<GroupBean>();{List<ChildBean> list1 = new ArrayList<ChildBean>();ChildBean cb1 = new ChildBean("妈妈", "123");ChildBean cb2 = new ChildBean("爸爸", "456");ChildBean cb3 = new ChildBean("爷爷", "789");ChildBean cb4 = new ChildBean("妹妹", "000");list1.add(cb1);list1.add(cb2);list1.add(cb3);list1.add(cb4);GroupBean gb1 = new GroupBean("家", list1);list.add(gb1);}{List<ChildBean> list1 = new ArrayList<ChildBean>();ChildBean cb1 = new ChildBean("张三", "123");ChildBean cb2 = new ChildBean("李四", "456");ChildBean cb3 = new ChildBean("王五", "789");ChildBean cb4 = new ChildBean("赵六", "000");ChildBean cb5 = new ChildBean("风起", "1111");ChildBean cb6 = new ChildBean("马坝", "222");ChildBean cb7 = new ChildBean("迁就", "3333333");list1.add(cb1);list1.add(cb2);list1.add(cb3);list1.add(cb4);list1.add(cb5);list1.add(cb6);list1.add(cb7);GroupBean gb1 = new GroupBean("我的朋友", list1);list.add(gb1);}{List<ChildBean> list1 = new ArrayList<ChildBean>();ChildBean cb1 = new ChildBean("Tom", "123");ChildBean cb2 = new ChildBean("Jerry", "456");ChildBean cb4 = new ChildBean("Bush", "000");list1.add(cb1);list1.add(cb2);list1.add(cb4);GroupBean gb1 = new GroupBean("国际友人", list1);list.add(gb1);}{List<ChildBean> list1 = new ArrayList<ChildBean>();ChildBean cb1 = new ChildBean("赵工", "123");ChildBean cb2 = new ChildBean("马工", "456");ChildBean cb3 = new ChildBean("王工", "789");ChildBean cb4 = new ChildBean("李工", "000");ChildBean cb5 = new ChildBean("为工", "000");list1.add(cb1);list1.add(cb2);list1.add(cb3);list1.add(cb4);list1.add(cb5);GroupBean gb1 = new GroupBean("同事", list1);list.add(gb1);}}
}

这里有两行代码我稍微说一下mListView.setGroupIndicator(null);表示不使用系统提供的展开和收起的图标,mListView.expandGroup(0);表示默认打开第一项。

好了,就说这些,有问题欢迎留言讨论。

本文源码下载地址https://github.com/lenve/expandablelistviewtest1

android开发之ExpandableListView的使用,实现类似QQ好友列表相关推荐

  1. Android中实现类似qq好友列表展开收起的效果

    最近两天学习实现了一个功能,感觉很好,一定要记录下来. 在网上找了一些资料,林林总总,总是不那么齐全,有的代码做成小Demo还会报错,需要自己调试半天.也幸好如此,我将此功能涉及到的一些知识点理解的更 ...

  2. Android开发之ExpandableListView

    编辑器加载中...   http://www.cdtarena.com/gpx/201207/4304.html 有时候,使用ListView并不能满足应用程序所需要的功能.有些应用程序需要多组Lis ...

  3. Android开发之ExpandableListView可拓展列表和子item左滑结合

    Hello!各位大神好,这是我的第一篇博客,大二学生初学安卓还不到几个月,所以希望不足之处能够多多指教. 在Android开发中,我们经常会遇到点击,展开,可拓展列表的使用,同时可恶的产品经理还要求你 ...

  4. Android开发之ExpandableListView: 可展开的ListView

    ExpandableListView: 可展开的ListView ListView 对于Android开发者来说是再熟悉不过的了,不过ListView的功能也有限.当需要展示第二层级数据时,使用Exp ...

  5. 基于Qt的类似QQ好友列表抽屉效果的实现

    转载地址: http://blog.csdn.net/shuideyidi/article/details/30619167 前段时间在忙毕业设计,所以一直没有更新博客.今天答辩完以后,将对我的毕业设 ...

  6. ExpandableListView仿QQ好友列表

    本例中,对ExpandableListView中的数据进行了封装,分为两个JavaBean,一个为Group类表示组信息,一个Child类表示该组下子列表信息: Group: public class ...

  7. Qt可拖拽排序表格(类似QQ好友分组排序)

    1,简介 为了最佳体验,一个拖拽行排序的功能研究了几个小时.效果参考的QQ好友分组的排序. 网上查了下好像没有人发布QT版类似的代码,于是自己动手 QQ好友分组排序效果: 2,效果 这是最终效果图,有 ...

  8. Qt可拖拽排序表格(解决滚动条不兼容问题,类似QQ好友分组排序)

    原版链接 https://blog.csdn.net/dpsying/article/details/77206127 Qt可拖拽排序表格(类似QQ好友分组排序) 感谢博主无私分享 修改后,解决了滚动 ...

  9. Android开发之TextView高级应用

    Android开发之TextView高级应用 我们平时使用TextView往往让它作为一个显示文字的容器,但TextView的功能并不局限于此.以下就和大家分享一下TextView的一些使用技巧. A ...

最新文章

  1. EmbeddedWebBrowser(EmbeddedWB)不显示图片
  2. JavaScript实现floatAsBinaryString浮点转为二进制字符串算法(附完整源码)
  3. linux 测试环境启用jar_Linux下搭建测试环境
  4. 4.10/4.11/4.12 lvm讲解 4.13 磁盘故障小案例
  5. linux 自动化管理工具,linux环境下搭建自动化Jenkins管理工具
  6. not null primary key什么意思_为什么我使用了索引,查询还是慢?
  7. 单一世界十万在线webgame的设计思路(五)-- 整体架构和总结
  8. 最全 Yaml 语法详解
  9. think PHP前台模板,thinkphp5(二)前台模板的引入
  10. 【图像搜索】基于pytorch官方预训练模型的简易相似图片搜索
  11. 你离大牛就差这10家国内知名的慕课网站。
  12. 性能测试线上培训班怎么选 3点教你在线选好培训班
  13. Maven 阿里云配置 此 MAVEN 配置地表最强不接受反驳
  14. 【观察】打造智能决策“新引擎”,杉数科技勇闯“无人区”
  15. 基于ETest的发动机ECU硬件在环测试平台的研究与开发
  16. 【数据结构】用堆排序解决TOPK问题
  17. springboot 集成redis key乱码\xac\xed\x00\x05t\x00\x0eHAOKE_HOT_WORD
  18. ubuntu1604安装sougou输入法
  19. 构建LVS负载均衡群集——地址转换模式(LVS-NAT)
  20. dependence walker

热门文章

  1. 【无标题】闲习业:分享一下副业兼职创业的方法
  2. 帆软报表行序号自动生成
  3. 春季盛行疾病 慎重管好口关
  4. 哲理小故事连载篇(一)
  5. 前端canvas能压缩图片?
  6. 小姨又又来了之!给我儿子写一个英语闯关脚本!好还会Python
  7. Jetpack——LiveData与ViewBinding
  8. 视频中的颜色识别——opencv实现
  9. 学术身份证:ORCID和ORCID iD,如何注册、获取并投稿使用?
  10. 如何在 Windows 10/11 中永久关闭 Windows Defender