android开发之ExpandableListView的使用,实现类似QQ好友列表
由于工作需要,今天简单研究了一下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() {
}
@Override
public int getGroupCount() {
return list.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return list.get(groupPosition).getChildren().size();
}
@Override
public Object getGroup(int groupPosition) {
return list.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return list.get(groupPosition).getChildren().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 false;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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;
@Override
protected 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);
表示默认打开第一项。
好了,就说这些,有问题欢迎留言讨论。
版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。
android开发之ExpandableListView的使用,实现类似QQ好友列表的更多相关文章
- Android开发之ExpandableListView扩展(BaseExpandableListAdapter的使用)(完整版)
Android开发之ExpandableListView扩展(BaseExpandableListAdapter的使用)(完整版)
- iOS UITableView制作类似QQ好友列表视图
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDele ...
- ExpandableListView仿QQ好友列表
本例中,对ExpandableListView中的数据进行了封装,分为两个JavaBean,一个为Group类表示组信息,一个Child类表示该组下子列表信息: Group: public class ...
- Android开发之Java集合类性能分析
对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天Android吧(ard8. ...
- Android开发之InstanceState详解
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- 【Android UI】Android开发之View的几种布局方式及实践
引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...
- Android开发之旅: Intents和Intent Filters(理论部分)
引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...
- Android开发之Java必备基础
Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...
- Android 开发之旅:深入分析布局文件&又是“Hello World!”
http://www.cnblogs.com/skynet/archive/2010/05/20/1740277.html 引言 上篇可以说是一个分水岭,它标志着我们从Android应用程序理论进入实 ...
随机推荐
- LinearLayout按下(pressed)或获取焦点(focused)时背景设置不同颜色或图片
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id=&qu ...
- linux下 修改配置文件的命令
vi或vim 进入后,按i,屏幕下方会出现INSERT字样,此时可以修改内容 按ESC,退回命令模式 :x是保存退出 :q!是不保存退出
- java比较器Comparable接口和Comaprator接口
Comparable故名思意是比较,意思就是做比较的,然后进行排序. 1.什么是comparable接口 此接口强行对实现它的每个类的对象进行整体排序.此排序被称为该类的自然排序 ,类的 compar ...
- Hadoop家族学习路线图
主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeeper, Avro, Ambari, Chukwa,新增加的项 ...
- Mac 上Dock中添加“最近打开过的项目”(Recent Applications)
有一个特别有用的Stack,“最近打开过的项目”,建立方法如下: 1. 打开Terminal,输入以下命令 defaults write com.apple.dock persistent-other ...
- POJ 1511 Invitation Cards dij
分析:正向加边,反向加边,然后两遍dij #include<cstdio> #include<cstring> #include<queue> #include&l ...
- SAE网站搭建(2)
通过djangao admin界面无法添加汉字(unicode)的解决办法. 根源:mysql服务器的默认设置不支持unicode(utf8) 解决办法: 将/etc/mysql/my.cnf中utf ...
- [codevs3296]有序数组合并
题目描述 Description 合并两个有序数组A和B,使得结果依然有序. 进阶:合并两个有序数组A和B,假设A有n个数,B有m个数,A数组后面还有m个空余空间,需要将结果保存在A中. 请使用O(n ...
- Android 多线程 异步加载
Android 应用中需要显示网络图片时,图片的加载过程较为耗时,因此加载过程使用线程池进行管理, 同时使用本地缓存保存图片(当来回滚动ListView时,调用缓存的图片),这样加载和显示图片较为友好 ...
- Hbase集群无法关闭
执行stop-hbase.sh关闭Hbase服务器,提示一直在等待,查阅了很多网上的资料找到了答案.因为hbase的主要信息存储在zookeeper集群中,zookeeper集群没有正常启动会导致hb ...