一个视图显示垂直滚动两级列表中的条目。这不同于列表视图,允许两个层次,类似于QQ的好友分组。要实现这个效果的整体思路为:

1.要给ExpandableListView 设置适配器,那么必须先设置数据源。

2.数据源,就是此处的适配器类,此方法继承了BaseExpandableListAdapter,它是ExpandableListView的一个子类。需要重写里面的多个方法。方法的意思,代码中都有详细的注释。数据源中,用到了自定义的View布局,此时根据自己的需求,来设置组和子项的布局样式。getChildView()和getGroupView()方法设置自定义布局。

3.数据源设置好,直接给ExpandableListView.setAdapter()即可实现此收缩功能。

下面是我自己简单做的一个显示效果:

layout中主视图expandable_layout.xml(ExpandableListView布局):

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/el">
</ExpandableListView>
</LinearLayout>

Layout中group_layout.xml(分组组名展示布局):

 <?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"
android:orientation="horizontal" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher"
android:id="@+id/iv_group" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_group" />
</LinearLayout>

Layout中child_layout.xml(子菜单item布局):

 <?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"
android:orientation="horizontal" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="50dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher"
android:id="@+id/iv_item" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_item" />
</LinearLayout>

Layout中alertdialog_layout.xml(AlertDialog自定义显示布局):

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et"
android:hint="请输入想对他说的话"/>
</LinearLayout>

Activity中Java实现代码(ExpandableListViewDemo.java):

 import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by panchengjia on 2016/12/2.
*/
public class ExpandableListViewDemo extends AppCompatActivity {
ExpandableListView el;
//定义分组名以及对应的图片数组,需一一对应
String[] country={"魏国","蜀国","吴国"};
int[] icon={R.mipmap.wei,R.mipmap.shu,R.mipmap.wu};
//使用二维定义组内成员以及对应头像,同样需要以一一对应
String[][] heros={{"司马懿","郭嘉","夏侯惇","甄姬"},{"刘备","赵云","张飞"},{"孙权","周瑜"}};
int[][] icons={{R.mipmap.simayi,R.mipmap.guojia,R.mipmap.xiahoudun,R.mipmap.zhenji},
{R.mipmap.liubei,R.mipmap.zhaoyun,R.mipmap.zhangfei},{R.mipmap.sunquan,R.mipmap.zhouyu}};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.expandable_layout);
el= (ExpandableListView) findViewById(R.id.el);
//设置点击下拉子菜单的监听事件
el.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
//获取分组成员的姓名
TextView tv = (TextView) v.findViewById(R.id.tv_item);
String name = tv.getText().toString();
//调用show方法(自定义AlertDialog)
show(v,name);
return false;
}
});
el.setAdapter(new MyAdapter());//设置自定义适配器
}
//定义show方法调出AlertDialog(不再赘述,详情请看前期相关博文,文章末尾有链接)
public void show(View v,String name){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(name);//设置标题名为传入的字符串(分组内点击对应的人物名)
View msg = getLayoutInflater().inflate(R.layout.altertdialog_layout,null);
builder.setView(msg);
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(ExpandableListViewDemo.this, "已发送", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(ExpandableListViewDemo.this, "不想说了", Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
//设置自定义适配器
class MyAdapter extends BaseExpandableListAdapter{
//获取国家个数
@Override
public int getGroupCount() {
return country.length;
}
//获取每个国家对应的人数
@Override
public int getChildrenCount(int groupPosition) {
return heros[groupPosition].length;
}
//获取对应国家名
@Override
public Object getGroup(int groupPosition) {
return country[groupPosition];
}
//获取对应国家对应的任务
@Override
public Object getChild(int groupPosition, int childPosition) {
return heros[groupPosition][childPosition];
}
//获取选择的国家对应数组下标
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
//获取选择的任务对应数组下标
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
//表示人物和国家ID是否稳定的更改底层数据
@Override
public boolean hasStableIds() {
return true;
}
//获取一个视图显示国家名以及对应的图标(ListView适配器优化)
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
ViewHolder vh;
if(convertView==null){
convertView=getLayoutInflater().inflate(R.layout.group_layout,null);
vh=new ViewHolder();
vh.tv= (TextView) convertView.findViewById(R.id.tv_group);
vh.iv= (ImageView) convertView.findViewById(R.id.iv_group);
convertView.setTag(vh);
}
vh= (ViewHolder) convertView.getTag();
vh.tv.setText(country[groupPosition]);
vh.iv.setImageResource(icon[groupPosition]);
return convertView;
}
//获取一个视图显示国家对应人物以及对应的图标(ListView适配器优化)
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ViewHolder vh;
if(convertView==null){
convertView=getLayoutInflater().inflate(R.layout.child_layout,null);
vh=new ViewHolder();
vh.tv= (TextView) convertView.findViewById(R.id.tv_item);
vh.iv= (ImageView) convertView.findViewById(R.id.iv_item);
convertView.setTag(vh);
}
vh= (ViewHolder) convertView.getTag();
vh.tv.setText(heros[groupPosition][childPosition]);
vh.iv.setImageResource(icons[groupPosition][childPosition]);
return convertView;
}
class ViewHolder{
ImageView iv;
TextView tv;
}
//设置子选项(对应人物)是可选的
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
}

补充说明:

java实现代码中用到自定义适配器ListView的优化,优化步骤如下:

(1)使用固定宽高(match_parent)的ListView,有助于在填充item(ListView中每行的布局)时避免重复渲染ListView组件,导致重复多次调用getView方法。

(2)Convertview用来重复使用已被隐藏的item对象,从而避免重复创建每个item的view对象。

(3)使用ViewHolder优化提高容器中查找组件的效率。

相关博文链接:

Android中的AlertDialog使用示例五(自定义对话框)

Android中使用ExpandableListView实现好友分组的更多相关文章

  1. Android中使用ExpandableListView实现微信通讯录界面(完善仿微信APP)

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

  2. android 中的ExpandableListView取消一级图标

    mainlistview = (ExpandableListView) view.findViewById(R.id.listview_myteacher); mainlistview.setGrou ...

  3. 【转】Android菜单详解——理解android中的Menu--不错

    原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...

  4. Android中ExpandableListView的使用

    ExpandableListView是Android中可以实现下拉list的一个控件,具体的实现方法如下: 首先:在layout的xml文件中定义一个ExpandableListView < L ...

  5. android开发之ExpandableListView的使用,实现类似QQ好友列表

    由于工作需要,今天简单研究了一下ExpandableListView,做了一个类似QQ列表的Demo,和大家分享一下. 效果图如下: 先来看看主布局文件: <RelativeLayout xml ...

  6. Android中ExpandableListView控件基本使用

    本文採用一个Demo来展示Android中ExpandableListView控件的使用,如怎样在组/子ListView中绑定数据源.直接上代码例如以下: 程序结构图: layout文件夹下的 mai ...

  7. Android数据适配-ExpandableListView

    Android中ListView的用法基本上学的时候都会使用,其中可以使用ArrayAdapter,SimpleAdapter,BaseAdapter去实现,这次主要使用的ExpandableList ...

  8. Android中通信协议

    一.TCP/IP协议(传输层协议) 1.Socket与ServerSocket Socket是应用层与TCP/IP协议簇通讯的中间抽象层,Socket是一组接口,在设计模式中,Socket的设计就是门 ...

  9. Android 中常见控件的介绍和使用

    1 TextView文本框 1.1 TextView类的结构 TextView 是用于显示字符串的组件,对于用户来说就是屏幕中一块用于显示文本的区域.TextView类的层次关系如下: java.la ...

随机推荐

  1. python之类介绍

    python对象销毁(垃圾回收): 1>同Java语言一样,python使用了引用计数这一简单计数来追踪内存中的对象,也就是说,python内部记录着所有使用中的对象各有多少引用,一个内部跟踪变 ...

  2. android内部培训视频_第四节(1)_异步网络操作

    第四节(1):异步网络操作  一.结合asyncTask下载网络图片 1.定义下载类,继承自asyncTask,参数分别为:String(url地址),Integer(刻度,本例没有用到),BitMa ...

  3. ABP框架 - 数据过滤

    文档目录 本节内容: 简介 预定义过滤 ISoftDelete 何时可用? IMustHaveTenant 何时可用? IMayHaveTenant 何时可用? 禁用过滤 关于using声明 关于多租 ...

  4. 学习python

    最近感觉Python 很不错的样子,乘着这次寒假,不如就先学一下吧. 翻看了一些教程,发现<python 简明教程>质量上乘. 我目前学习python就是打算做一些上位机之类的,好像有点杀 ...

  5. Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结

    Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结 1. 验证码的前世今生11.1. 第一代验证码 图片验证码11.2. 第二代验证码  用户操作 ,比如 ...

  6. 【.net 深呼吸】使用二进制格式来压缩XML文档

    在相当多的情况下,咱们写入XML文件默认是使用文本格式来写入的,如果XML内容是通过网络传输,或者希望节省空间,特别是对于XML文档较大的情况,是得考虑尽可能地压缩XML文件的大小. XmlDicti ...

  7. 基本数据结构(1)——算法导论(11)

    1. 引言     从这篇博客开始,来介绍一些基本的数据结构知识.本篇及下一篇会介绍几种基本的数据结构:栈.队列.链表和有根树.此外还会介绍由数组构造对象和指针的方法.     这一篇主要介绍栈和队列 ...

  8. Android总结之Gzip/Zip压缩

    前言: 做过Android网络开发的都知道,在网络传输中我们一般都会开启GZIP压缩,但是出于刨根问底的天性仅仅知道如何开启就不能满足俺的好奇心的,所以想着写个demo测试一下比较常用的两个数据压缩方 ...

  9. .NET Core的文件系统[2]:FileProvider是个什么东西?

    在<读取并监控文件的变化>中,我们通过三个简单的实例演示从编程的角度对文件系统做了初步的体验,接下来我们继续从设计的角度来继续认识它.这个抽象的文件系统以目录的形式来组织文件,我们可以利用 ...

  10. XML技术之SAX解析器

    1.解析XML文件有三种解析方法:DOM SAX DOM4J. 2.首先SAX解析技术只能读取XML文档中的数据信息,不能对其文档中的数据进行添加,删除,修改操作:这就是SAX解析技术的一个缺陷. 3 ...