Android ExpandableListView 分组列表

Android ExpandableListView ( 分组列表 ) 是一个有两层的 ListView,也就是一个分组列表,有点类似于微信通讯录(ABCDE) 那样的

ExpandableListView 继承自 ListView,也使用 Adapter 提供数据

ExpandableListView

使用 XMLD 创建 ExpandableListView 很简单

<ExpandableListView
    android:id="@+/contact_list"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" />

使用 android:layout_height 给 ExpandableListView 定义高度时,如果父容器使用的是 wrap_content 这种高度不确定的,那么它也不可以使用 wrap_content,只有父容器使用的是确定高度,比如 300dp, 才可以使用 wrap_content

ExpandableListView 属性

属性 说明
android:childDivider 指定各组内子类表项之间的分隔条,图片不会完全显示,分离子列表项的是一条直线
android:childIndicator 显示在子列表旁边的Drawable对象,可以是一个图像
android:childIndicatorEnd 子列表项指示符的结束约束位置
android:childIndicatorLeft 子列表项指示符的左边约束位置
android:childIndicatorRight 子列表项指示符的右边约束位置
android:childIndicatorStart 子列表项指示符的开始约束位置
android:groupIndicator 显示在组列表旁边的Drawable对象,可以是一个图像
android:indicatorEnd 组列表项指示器的结束约束位置
android:indicatorLeft 组列表项指示器的左边约束位置
android:indicatorRight 组列表项指示器的右边约束位置
android:indicatorStart 组列表项指示器的开始约束位置

ExpandableListView 事件

事件 说明
OnChildClickListener 分组列表子项被点击时触发
OnGroupClickListener 分组列表分组项被点击时触发
OnGroupCollapseListener 分组列表折叠时触发
OnGroupExpandListener 分组列表展开时触发

ExpandableListView 的 Adapter

给 ExpandableListView 用的 Adapter 有三种实现方式

  1. 继承 BaseExpandableListAdpter 实现 ExpandableAdapter

    扩展 BaseExpandableListAdpter 实现 ExpandableAdapter 的重点是要实现 组 和 子列表

  2. 使用 SimpleExpandableListAdpater 将两个 List 集合包装成 ExpandableAdapter

  3. 使用 simpleCursorTreeAdapter 将 Cursor 中的数据包装成 SimpleCuroTreeAdapter

看起来后面两个比较复杂,所以,我们还是用第一种方式吧

范例

先来看看最后的效果


  1. 创建一个 空的 Android 项目 cn.twle.android.ExpandableListView

  2. 下载 /static/i/android/lol_hero_list.zip,解压并把所有的图片拖到 res/drawable

  3. 修改 activity_main.xml 添加一个 AutoCompleteTextView

    <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:padding="5dp"
        tools:context=".MainActivity">
    
        <ExpandableListView
            android:id="@+id/lol_hero_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:childDivider="#dddddd"/>
    
    </RelativeLayout>
    
  4. 在 res/layout 目录下新建一个分组列表中组项的布局 hero_group_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:padding="5dp">
    
        <TextView
            android:id="@+id/group_name"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:gravity="center_vertical"
            android:paddingLeft="30dp"
            android:text="AP"
            android:textStyle="bold"
            android:textSize="20sp" />
    
    </LinearLayout>
    
  5. 在 res/layout 目录下新建一个分组列表中数据项的布局 hero_list_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:padding="5dp"
        android:background="#eeeeee">
    
        <ImageView
            android:id="@+id/hero_icon"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:src="@drawable/lol_icon1"
            android:focusable="false"/>
    
        <TextView
            android:id="@+id/hero_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="15dp"
            android:focusable="false"
            android:text="提莫"
            android:textSize="18sp" />
    </LinearLayout>
    
  6. 在 MainActivity.java 同一个目录下新建一个 GroupBean.java

    package cn.twle.android.expandablelistview;
    
    public class GroupBean {
    
        private String name;
    
        public GroupBean() {
        }
    
        public GroupBean(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
  7. 在 MainActivity.java 同一个目录下新建一个 HeroBean.java

    package cn.twle.android.expandablelistview;
    
    public class HeroBean {
    
        private int icon;
        private String name;
    
        public HeroBean() {
        }
    
        public HeroBean(int icon, String name) {
    
            this.icon = icon;
            this.name = name;
        }
    
        public int getIcon() {
            return icon;
        }
    
        public String getName() {
            return name;
        }
    
        public void setIcon(int icon) {
            this.icon = icon;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
  8. 在 MainActivity.java 同一个目录下新建一个 MsExpandableListAdapter

    package cn.twle.android.expandablelistview;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseExpandableListAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    
    public class MsExpandableListAdapter extends BaseExpandableListAdapter {
    
        private ArrayList<GroupBean> gData;
        private ArrayList<ArrayList<HeroBean>> iData;
        private Context mContext;
    
        public MsExpandableListAdapter(ArrayList<GroupBean> gData,ArrayList<ArrayList<HeroBean>> iData, Context mContext) {
            this.gData = gData;
            this.iData = iData;
            this.mContext = mContext;
        }
    
        @Override
        public int getGroupCount() {
            return gData.size();
        }
    
        @Override
        public int getChildrenCount(int groupPosition) {
            return iData.get(groupPosition).size();
        }
    
        @Override
        public GroupBean getGroup(int groupPosition) {
            return gData.get(groupPosition);
        }
    
        @Override
        public HeroBean getChild(int groupPosition, int childPosition) {
            return iData.get(groupPosition).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) {
    
            ViewHolderGroup groupHolder;
            if(convertView == null){
                convertView = LayoutInflater.from(mContext).inflate(
                        R.layout.hero_group_item, parent, false);
                groupHolder = new ViewHolderGroup();
                groupHolder.group_name = (TextView) convertView.findViewById(R.id.group_name);
                convertView.setTag(groupHolder);
            }else{
                groupHolder = (ViewHolderGroup) convertView.getTag();
            }
            groupHolder.group_name.setText(gData.get(groupPosition).getName());
            return convertView;
        }
    
        //取得显示给定分组给定子位置的数据用的视图
        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
            ViewHolderItem itemHolder;
            if(convertView == null){
                convertView = LayoutInflater.from(mContext).inflate(
                        R.layout.hero_list_item, parent, false);
                itemHolder = new ViewHolderItem();
                itemHolder.hero_icon = (ImageView) convertView.findViewById(R.id.hero_icon);
                itemHolder.hero_name = (TextView) convertView.findViewById(R.id.hero_name);
                convertView.setTag(itemHolder);
            }else{
                itemHolder = (ViewHolderItem) convertView.getTag();
            }
            itemHolder.hero_icon.setImageResource(iData.get(groupPosition).get(childPosition).getIcon());
            itemHolder.hero_name.setText(iData.get(groupPosition).get(childPosition).getName());
            return convertView;
        }
    
        //设置子列表是否可选中
        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }
    
        private static class ViewHolderGroup{
            private TextView group_name;
        }
    
        private static class ViewHolderItem{
            private ImageView hero_icon;
            private TextView hero_name;
        }
    
    }
    
  9. 最后是修改 MainActivity.java

    package cn.twle.android.expandablelistview;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.ExpandableListView;
    import android.widget.Toast;
    
    import java.util.ArrayList;
    
    public class MainActivity extends AppCompatActivity {
    
        private ArrayList<GroupBean> gData = null;
        private ArrayList<ArrayList<HeroBean>> iData = null;
        private ArrayList<HeroBean> lData = null;
        private Context mContext;
        private ExpandableListView lol_hero_list;
        private MsExpandableListAdapter msAdapter = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mContext = MainActivity.this;
            lol_hero_list = (ExpandableListView) findViewById(R.id.lol_hero_list);
    
            //数据准备
            gData = new ArrayList<GroupBean>();
            iData = new ArrayList<ArrayList<HeroBean>>();
            gData.add(new GroupBean("AD"));
            gData.add(new GroupBean("AP"));
            gData.add(new GroupBean("TANK"));
    
            lData = new ArrayList<HeroBean>();
    
            //AD组
            lData.add(new HeroBean(R.drawable.lol_icon3,"剑圣"));
            lData.add(new HeroBean(R.drawable.lol_icon4,"德莱文"));
            lData.add(new HeroBean(R.drawable.lol_icon13,"男枪"));
            lData.add(new HeroBean(R.drawable.lol_icon14,"韦鲁斯"));
            iData.add(lData);
            //AP组
            lData = new ArrayList<HeroBean>();
            lData.add(new HeroBean(R.drawable.lol_icon1, "提莫"));
            lData.add(new HeroBean(R.drawable.lol_icon7, "安妮"));
            lData.add(new HeroBean(R.drawable.lol_icon8, "天使"));
            lData.add(new HeroBean(R.drawable.lol_icon9, "泽拉斯"));
            lData.add(new HeroBean(R.drawable.lol_icon11, "狐狸"));
            iData.add(lData);
            //TANK组
            lData = new ArrayList<HeroBean>();
            lData.add(new HeroBean(R.drawable.lol_icon2, "诺手"));
            lData.add(new HeroBean(R.drawable.lol_icon5, "德邦"));
            lData.add(new HeroBean(R.drawable.lol_icon6, "奥拉夫"));
            lData.add(new HeroBean(R.drawable.lol_icon10, "龙女"));
            lData.add(new HeroBean(R.drawable.lol_icon12, "狗熊"));
            iData.add(lData);
    
            msAdapter = new MsExpandableListAdapter(gData,iData,mContext);
            lol_hero_list.setAdapter(msAdapter);
    
            //为列表设置点击事件
            lol_hero_list.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
                @Override
                public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                    Toast.makeText(mContext, "你点击了:" + iData.get(groupPosition).get(childPosition).getName(), Toast.LENGTH_SHORT).show();
                    return true;
                }
            });
    
        }
    }
    

参考文档

  1. Android ExpandableListView

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

♥   简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.