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_heightExpandableListView 定义高度时,如果父容器使用的是 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. 使用 simpleCursorTreeAdapterCursor 中的数据包装成 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.