1--∞:不一样的 ExpandableListView

前言


此篇文章只是本人学习 ExpandableListView 控件使用的笔记,如有雷同,纯属缘分!

首先我们来了解什么是 ExpandableListView ?

官方直译 (无需翻墙):
A view that shows items in a vertically scrolling two-level list. This differs from the ListView by allowing two levels: groups which can individually be expanded to show its children. The items come from the ExpandableListAdapter associated with this view
(一种用于垂直滚动展示两级列表的视图,和ListView的不同之处就是它可以展示两级列表,分组可以单独展开显示子选项。这些选项的数据是通过ExpandableListAdapter关联的)

本人理解:一个可以展示两级列表的试图,并且可以收缩子选项的控件,类似与 QQ 好友列表那种!

还是一言不合就上图

custom.gif

上面的效果是不是和一般的 ExpandableListView 不一样呀!这次的 ExpandableListView 控件的子项是横向的。现在我们就来实现上面的效果!

如果想实现原始的 ExpandableListView 请看下面的文章
Android ExpandableListView使用小结(一)
http://www.open-open.com/lib/view/open1406014566679.html

Now,我们来实现上面的效果:

第一步 创建 activity_main 布局文件 里面包含 ExpandableListView:

activity_main.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="match_parent"> 
   <ExpandableListView 
         android:id="@+id/expandableListView"  
         android:layout_width="match_parent" 
         android:layout_height="match_parent"
         android:groupIndicator="@null"/>
</RelativeLayout>

上面的布局就是一个简单 ExpandableListView 并没有什么多余的属性,如果想了解更多属性请点击 传送门 传送到官网!

第二步 定义定义 MainActivity

MainActivity.java

public class MainActivity extends AppCompatActivity {

          @Override
          protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                ExpandableListView expandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
                //自定义适配器
                MeExpandableListAdapter mExpandableListAdapter = new MeExpandableListAdapter(MainActivity.this) ;
                expandableListView.setAdapter(mExpandableListAdapter);
                //默认展开的是那个
                groupexpandableListView.expandGroup(0);
         }
}

MainActivity 中的代码很简单,主要的代码还是在自定义适配器 MeExpandableListAdapter 那里,现在我们来实现它。

第三步 实现自定义 MeExpandableListAdapter

(1) ExpandableListView 控件是由有分组视图(group)和子选项视图(child)组成的,所以现在先来定义它的分组视图(group)和子选项视图(child):

a.定义分组视图(group)
expandablelistview_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="wrap_content">
    <ImageView
        android:id="@+id/group_icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_margin="10dp"/>
    <TextView
        android:id="@+id/group_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:layout_marginStart="10dp"
        android:layout_toEndOf="@id/group_icon"
        android:text=""
        android:textColor="#000000"
        android:textSize="20sp"/>
    <ImageView
        android:id="@+id/group_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:layout_marginEnd="5dp"/>
</RelativeLayout>

上面就是分组视图(group)的布局文件就是一个图标+标题+收缩图标,你也可以自己定义这个布局;

b.定义子选项视图(child)
expandablelistview_child.xml

<?xml version="1.0" encoding="utf-8"?>
<GridView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/child_gridView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#eeeeee"
    android:numColumns="4"/>

在子选项视图(child)中我选择以一个 GridView 控件 这样我就能横向的显示子选项视图(child);

c.定义子选项视图(child)中 GridView 中的item布局

<?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="wrap_content"
    android:layout_centerInParent="true">
    <ImageView
        android:id="@+id/child_gridview_icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerHorizontal="true"
        android:contentDescription="@string/app_name"/>
    <TextView
        android:id="@+id/child_gridview_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/child_gridview_icon"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="3dp"
        android:text=""
        android:textColor="#000000"
        android:textSize="15sp"/>
</RelativeLayout>
到现在我们把自定义适配器相关的布局都写好了,我们就来实现 MeExpandableListAdapter

(2)自定义 ExpandableListView的适配器 MeExpandableListAdapter (代码略长)
MeExpandableListAdapter.java

public class MeExpandableListAdapter extends BaseExpandableListAdapter {
    //分组视图(group)的标题
    private String[] group = {"group1", "group2"};
    //分组视图(group)的图标
    private int[] groupicon = {R.mipmap.group_icon_1, R.mipmap.group_icon_2};
    //子选项视图(child) 的标题
    private String[][] gridViewChild = {{"child11", "child12"}, {"child21", "child22"}};
    //子选项视图(child) 的图标
    private int[][] gridImgChild = new int[][]{
            {R.mipmap.ic_launcher, R.mipmap.ic_launcher},
            {R.mipmap.ic_launcher, R.mipmap.ic_launcher}
    };
    private String[][] child = {{""}, {""}};
    private LayoutInflater mInflater;
    private Context context;
    public MeExpandableListAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
        this.context = context;
    }
    //expandablelistview的分组数
    @Override
    public int getGroupCount() {
        return group.length;
    }
    //取得指定分组的子元素数
    @Override
    public int getChildrenCount(int groupPosition) {
        return child[groupPosition].length;
    }
    //取得与给定分组关联的数据
    @Override
    public Object getGroup(int groupPosition) {
        return group[groupPosition];
    }
    //取得与给定子分组关联的数据
    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return child[groupPosition][childPosition];
    }
    //取得指定分组的ID.该组ID必须在组中是唯一的.必须不同于其他所有ID(分组及子项目的ID)
    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }
    //取得给定分组中给定子视图的ID. 该组ID必须在组中是唯一的.必须不同于其他所有ID(分组及子项目的ID)
    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }
    @Override
    public boolean hasStableIds() {
        return true;
    }
    //重写GroupView的布局
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,                             View convertView, ViewGroup parent) {
        if (convertView == null) {
            mViewChild = new ViewChild();
            convertView = mInflater.inflate(R.layout.expandablelistview_group, parent, false);
            mViewChild.textView = (TextView) convertView.findViewById(R.id.group_name);
            mViewChild.imageView = (ImageView) convertView.findViewById(R.id.group_indicator);
            mViewChild.imageHead = (ImageView) convertView.findViewById(R.id.group_icon);
            convertView.setTag(mViewChild);
        } else {
            mViewChild = (ViewChild) convertView.getTag();
        }
        if (isExpanded)
            mViewChild.imageView.setImageResource(R.mipmap.group_indicator_2);
        else
            mViewChild.imageView.setImageResource(R.mipmap.group_indicator_1);
        mViewChild.textView.setText(getGroup(groupPosition).toString());
        mViewChild.imageHead.setImageResource(groupicon[groupPosition]);
        return convertView;
    }
    //重写ChildView的布局
    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        if (convertView == null) {
            mViewChild = new ViewChild();
            convertView = mInflater.inflate(R.layout.expandablelistview_chilld, parent, false);
            mViewChild.gridView = (GridView) convertView.findViewById(R.id.child_gridView);
            convertView.setTag(mViewChild);
        } else {
            mViewChild = (ViewChild) convertView.getTag();
        }
        SimpleAdapter mSimpleAdapter = new SimpleAdapter(context,
                setGridViewData(gridViewChild[groupPosition],
                gridImgChild[groupPosition]),
                R.layout.chilld_gridview_item, new String[]{
                "child_gridview_item", "child_gridview_img1"},
                new int[]{R.id.child_gridview_item,
                        R.id.child_gridview_icon});
        mViewChild.gridView.setAdapter(mSimpleAdapter);
        setGridViewListener(mViewChild.gridView, groupPosition);
        return convertView;
    }
    //设置GridView点击事件监听
    private void setGridViewListener(final GridView gridView, final int groupPosition) {
        gridView.setOnItemClickListener(new GridView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,                                    int position, long id) {
                RelativeLayout ff = (RelativeLayout) view;
                TextView gg = (TextView) ff
                        .findViewById(R.id.child_gridview_item);
                Toast.makeText(context, "你点击了" + gg.getText().toString(), Toast.LENGTH_SHORT).show();
            }
        });
    }
    //设置GridView数据
    private ArrayList<HashMap<String, Object>> setGridViewData(String[] data,                                                               int[] img) {
        ArrayList<HashMap<String, Object>> gridItem = new ArrayList<>();        for (int i = 0; i < data.length; i++) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("child_gridview_item", data[i]);
            hashMap.put("child_gridview_img1", img[i]);
            gridItem.add(hashMap);
        }
        return gridItem;
    }
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
    ViewChild mViewChild;
    static class ViewChild {
        ImageView imageHead;
        ImageView imageView;
        TextView textView;
        GridView gridView;
    }
}

上面的代码都有注释,相信大家都看得懂。到此,我们就实现了 ExpandableListView 控件的子项是横向的效果。

总结

其实这次 ExpandableListVie 效果实现主要的就是自定义 BaseExpandableListAdapter 中 getChildView() 的方法,只要把 子选项视图换为一个 GridView 布局就行了(我想:如果子选项视图换成其他控件也行,下次试试)。

github地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,420评论 22 663
  • Android UI相关开源项目库汇总OpenDigg 抽屉菜单MaterialDrawer ★7337 - 安卓...
    黄海佳阅读 8,622评论 3 77
  • 姓名:陈权 公司:青柠养车 【知~学习】 《创造高收益》音频打卡第15天 《轻课口语》打卡第391天 【行~实践】...
    水青柠阅读 324评论 0 0
  • 我已经不记得有多久没有用文字书写心情了。 时间过的真快,转眼已经大学毕业两年了,随着时间的流逝,同学朋...
    旧提阅读 558评论 0 0
  • 你久仰过孤独的名字吗? 你看见过寂寞留下的背景吗? 你闻见过灵魂散发的香气吗? 这是一个流浪者的生命迹象。 在撒哈...
    断梦残生阅读 237评论 2 2