由于工作需要,今天简单研究了1下ExpandableListView,做了1个类似QQ列表的Demo,和大家分享1下。
效果图以下:
先来看看主布局文件:
<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,我们可以自定义1个适配器继承BaseExpandableListAdapter,实现该类中的1些方法便可。
代码以下:
public class MyAdapter extends BaseExpandableListAdapter { private Listlist; private Context context; public MyAdapter(Listlist, 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;
}
}
这里的代码有点长,我们略微解释1下,先是构造方法中传入两个参数,1个是数据源list,另外1个是上下文,list是1个GroupBean集合,GroupBean以下:
public class GroupBean { private String groupName; private Listchildren; public String getGroupName() { return groupName;
} public void setGroupName(String groupName) { this.groupName = groupName;
} public ListgetChildren() { return children;
} public void setChildren(Listchildren) { this.children = children;
} public GroupBean(String groupName, Listchildren) { this.groupName = groupName; this.children = children;
} public GroupBean() {
}
}
很明显,GroupBean有两个属性,1个是组名字,另外1个是该组下子项的1个集合,这个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,我们返回的时候还是组和组内的子项分开返回,代码很简单,就不多说了。略微长1点的方法就是getGroupView和getChildView,不多也都没啥逻辑,和我们在ListView中使用BaseAdapter中的getView方法差不多,不同的是数据赋值的时候有差别。
我个人觉得,使用ExpandableListView关键在于把数据结构弄清楚,Group和Child弄清楚了,其他的都很简单。
这里我把Group的布局和Child的布局贴出来给大家看看:
item_group.xml
<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
<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>
这里还触及到1个圆角方框,代码是这样的:
item_background_select.xml
<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 Listlist; @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); } private void initData() {
list = new ArrayList();
{
Listlist1 = new ArrayList();
ChildBean cb1 = new ChildBean("妈妈", "123");
ChildBean cb2 = new ChildBean("爸爸", "456");
ChildBean cb3 = new ChildBean("爷爷", "789");
ChildBean cb4 = new ChildBean("mm", "000");
list1.add(cb1);
list1.add(cb2);
list1.add(cb3);
list1.add(cb4);
GroupBean gb1 = new GroupBean("家", list1);
list.add(gb1);
}
{
Listlist1 = new ArrayList();
ChildBean cb1 = new ChildBean("张3", "123");
ChildBean cb2 = new ChildBean("李4", "456");
ChildBean cb3 = new ChildBean("王5", "789");
ChildBean cb4 = new ChildBean("赵6", "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);
}
{
Listlist1 = new ArrayList();
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);
}
{
Listlist1 = new ArrayList();
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);
}
}
}
这里有两行代码我略微说1下mListView.setGroupIndicator(null);表示不使用系统提供的展开和收起的图标,mListView.expandGroup(0);表示默许打开第1项。
好了,就说这些,有问题欢迎留言讨论。