可展开的列表组件——ExpandableListView深入解析

来源:互联网 发布:世界上第一个人工智能 编辑:程序博客网 时间:2024/06/04 18:21

可展开的列表组件——ExpandableListView深入解析

一、知识点
1、ExpandableListView常用XML属性
2.ExpandableListView继承BaseExpandableListAdapter后重写的各个函数详解
3.ExpandableListView自定义下拉图标

二、解析
2.1、ExpandableListView常用XML属性

2.1.1 设置点击item项后该item项的背景色

//当你选中某一个item项时,该item项的背景会变色,下面的值是将该背景色设置为透明android:listSelector="#00000000"

2.1.2 设置item项的高度

//这个是用在item的布局文件里android:minHeight="50dp"

2.1.3 拖动时背景图片问题

//在拖动的时候背景图片消失变成黑色背景,等到拖动完毕我们自己的背景图片才显示出来android:scrollingCache=”false” 或 android:cacheColorHint=”#00000000″

2.1.4 分割线高度

android:dividerHeight="1dp"

2.2ExpandableListView继承BaseExpandableListAdapter后重写的各个函数详解

下面的代码几乎每条都给了注释,就不再赘述了。

2.2.1 child.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="50dp"    android:orientation="horizontal" >    <TextView         android:id="@+id/tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_vertical"        android:layout_marginLeft="10dp"        android:textSize="18dp"        android:text="this"        /></LinearLayout>

2.2.2 group.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="wrap_content"    android:minHeight="50dp"    android:orientation="horizontal" >    <ImageView        android:layout_marginLeft="10dp"        android:layout_gravity="center_vertical"        android:id="@+id/arrow"        android:layout_width="25dp"        android:layout_height="25dp"        />    <TextView         android:layout_marginLeft="10dp"        android:id="@+id/logo"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="20dp"        android:layout_gravity="center_vertical"        /></LinearLayout>

2.2.3 colors.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <color name="gray">#BEBEBE</color>    <color name="SeaGreen1">#54FF9F</color></resources>

2.2.4 activity_main.xml

<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/container"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    >    <ExpandableListView         android:id="@+id/expandlist"        android:divider="@color/gray"        android:childDivider="@color/SeaGreen1"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:groupIndicator="@null"        android:listSelector="#00000000"        android:dividerHeight="1dp"        >    </ExpandableListView></LinearLayout>

2.2.5 MyExpandableListAdapter.java

package com.yds.example;import java.util.List;import java.util.Map;import android.content.Context;import android.database.DataSetObserver;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseExpandableListAdapter;import android.widget.ImageView;import android.widget.TextView;public class MyExpandableListAdapter extends BaseExpandableListAdapter {    //上下文    Context context;    //声明一个布局管理器对象    LayoutInflater inflater;    //声明一个组集合    List<Map<String, Object>>group;    //声明一个子元素集合    List<List<Map<String, Object>>>child;    //声明一个map对象    Map<String, Object>map;    /**     * 自定义适配器的构造函数     * @param context 上下文     * @param group 组集合     * @param child 子元素集合     */    public MyExpandableListAdapter(Context context,List<Map<String, Object>>group,List<List<Map<String, Object>>>child){        //初始化上下文        this.context = context;        //初始化布局管理器对象        inflater = LayoutInflater.from(context);        //初始化组集合        this.group = group;        //初始化子元素集合        this.child = child;    }    /**     * ExpandableListAdapter里面的所有条目     * 都可用吗?如果是yes,就意味着所有条目可以选择和点击了。     * 返回值:返回True表示所有条目均可用。     */    @Override    public boolean areAllItemsEnabled() {        // TODO Auto-generated method stub        return true;    }    /**     * 获取指定组中的指定子元素数据。      */    @Override    public Object getChild(int groupPosition, int childPosition) {        // TODO Auto-generated method stub        /*child.get(groupPosition)是得到groupPosition处的list对象,然后         * child.get(groupPosition).get(childPosition)得到child的map对象,然后         * child.get(groupPosition).get(childPosition).get("Child")是得到key值         * 为Child的值         * */        return child.get(groupPosition).get(childPosition).get("Child");    }    /**     * 获取指定组中的指定子元素ID,这个ID在组里一定是唯一的。联合ID(getCombinedChildId(long, long))在所有条目(所有组和所有元素)中也是唯一的。     */    @Override    public long getChildId(int groupPosition, int childPosition) {        // TODO Auto-generated method stub        /******子元素的位置********/        return childPosition;    }    /**获取一个视图对象,显示指定组中的指定子元素数据。     * @param groupPosition 组位置(该组内部含有子元素)     * @param childPosition 子元素位置(决定返回哪个视图)     * @param isLastChild 子元素是否处于组中的最后一个     * @param convertView 重用已经有的视图对象,它是RecycleBin缓存机制调用getScrapView方法获取废弃已缓存的view.     * @param parent 返回的视图(View)对象始终依附于的视图组。通俗的说是它的父视图。     */    @Override    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {        // TODO Auto-generated method stub        ViewHolderChild viewHolderChild;        /*当convertView为空,也就是没有废弃已缓存 view时,将执行下面方法,调用layoutinflate的         * inflate()方法来加载一个view。         * 如有不懂,请点击:http://blog.csdn.net/libmill/article/details/49644743         */        if(convertView==null){            //重新加载布局            convertView = inflater.inflate(R.layout.child, null);            //初始化控件管理器(自己命名的)            viewHolderChild = new ViewHolderChild();            //绑定控件id            viewHolderChild.tv = (TextView) convertView.findViewById(R.id.tv);            /*convertView的setTag将viewHolderChild设置到Tag中,以便系统第二次绘制                ExpandableListView时从Tag中取出            */            convertView.setTag(viewHolderChild);        }else{            //当convertView不为空时,从Tag中取出viewHolderChild            viewHolderChild = (ViewHolderChild) convertView.getTag();        }        //给子元素的TextView设置值        viewHolderChild.tv.setText(getChild(groupPosition, childPosition).toString());        //返回视图对象,这里是childPostion处的视图        return convertView;    }    /**     * 获取指定组中子元素的个数     */    @Override    public int getChildrenCount(int groupPosition) {        // TODO Auto-generated method stub        return child.get(groupPosition).size();    }    /**     * 从列表所有项(组或子项)中获得一个唯一的子ID号。可折叠列表要求每个元素(组或子项)在所有的子元素和组中     * 有一个唯一的ID。本方法负责根据所给的子ID号和组ID号返回唯一的ID。此外,若hasStableIds()     * 是true,那么必须要返回稳定的ID。     * @param groupId 包含该子元素的组ID     * @param childId 子元素的ID     * @return:列表所有项(组或子项)中唯一的(和可能稳定)的子元素ID号。(译者注:ID理论上是稳定的,     * 不会发生冲突的情况。也就是说,这个列表会有组、子元素,它们的ID都是唯一的。)      */    @Override    public long getCombinedChildId(long groupId , long childId ) {        // TODO Auto-generated method stub        return 0;    }    /**     * 获取组ID     * @param groupId 组ID     * @return :组ID     */    @Override    public long getCombinedGroupId(long groupId) {        // TODO Auto-generated method stub        return 0;    }    /**     * 得到指定组的组数据     * @param groupPosition:指定的组的位置     * @return 返回指定组的组数据     */    @Override    public Object getGroup(int groupPosition) {        // TODO Auto-generated method stub        /**group.get(groupPosition)获取map对象         * group.get(groupPosition).get("Group")获取key值为Group的数据         * **/        return group.get(groupPosition).get("Group");    }    /**     * 获取组长     */    @Override    public int getGroupCount() {        // TODO Auto-generated method stub        return group.size();    }    /**     * 获取指定组的Id     */    @Override    public long getGroupId(int groupPosition) {        // TODO Auto-generated method stub        return groupPosition;    }    /**     * 获取指定组的视图对象     * @param groupPosition:组位置(决定返回哪个视图)     * @param isExpanded:改组是展开状态还是伸缩状态     * @param convertView:重用已有的视图对象     * @return 返回指定组的视图对象     */    @Override    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {        // TODO Auto-generated method stub        ViewHolderGroup viewHolder;        //判断convertView是否为空,convertView是RecycleBean调用getScrapView函数得到废弃已缓存的view        if(convertView==null){            //初始化控件管理器对象            viewHolder = new ViewHolderGroup();            //重新加载布局            convertView = inflater.inflate(R.layout.group, null);            //给组元素绑定ID            viewHolder.logo_tv = (TextView) convertView.findViewById(R.id.logo);            //给组元素箭头绑定ID            viewHolder.arrow = (ImageView) convertView.findViewById(R.id.arrow);            //convertView将viewHolder设置到Tag中,以便再次绘制ExpandableListView时从Tag中取出viewHolder;            convertView.setTag(viewHolder);        }else {//如果convertView不为空,即getScrapView得到废弃已缓存的view            //从Tag中取出之前存入的viewHolder            viewHolder = (ViewHolderGroup) convertView.getTag();        }        //设置组值        viewHolder.logo_tv.setText(getGroup(groupPosition).toString());        //如果组是展开状态        if (isExpanded) {            //箭头向下            viewHolder.arrow.setImageResource(R.drawable.arrow_down);        }else{//如果组是伸缩状态            //箭头向右            viewHolder.arrow.setImageResource(R.drawable.arrow);        }        //返回得到的指定组的视图对象        return convertView;    }    /**     * 组和子元素是否持有稳定的ID,也就是底层数据的改变不会影响到它们。     * @return 返回一个Boolean类型的值,如果为TRUE,意味着相同的ID永远引用相同的对象     */    @Override    public boolean hasStableIds() {        // TODO Auto-generated method stub        return false;    }    /**     * 是否选中指定位置上的子元素。     */    @Override    public boolean isChildSelectable(int arg0, int arg1) {        // TODO Auto-generated method stub        return true;    }    /**     * 如果当前适配器不包含任何数据则返回True。经常用来决定一个空视图是否应该被显示。     * 一个典型的实现将返回表达式getCount() == 0的结果,但是由于getCount()包含了头部和尾部,适配器可能需要不同的行为。     */    @Override    public boolean isEmpty() {        // TODO Auto-generated method stub        return false;    }    /**     * 当组收缩状态的时候此方法被调用。     */    @Override    public void onGroupCollapsed(int groupPosition) {        // TODO Auto-generated method stub    }    /**     * 当组展开状态的时候此方法被调用。     */    @Override    public void onGroupExpanded(int groupPosition) {        // TODO Auto-generated method stub    }    /**     * 注册一个观察者(observer),当此适配器数据修改时即调用此观察者。     * @param observer:当数据修改时通知调用的对象     */    @Override    public void registerDataSetObserver(DataSetObserver observer) {        // TODO Auto-generated method stub    }    /**     * 取消先前通过registerDataSetObserver(DataSetObserver)方式注册进该适配器中的观察者对象。     * @param observer 取消这个观察者的注册     */    @Override    public void unregisterDataSetObserver(DataSetObserver observer) {        // TODO Auto-generated method stub    }    /**     * 组控件管理器     * @author Administrator     *     */    class ViewHolderGroup{        TextView logo_tv;        ImageView arrow;    }    /**     * 子控件管理器     * @author Administrator     *     */    class ViewHolderChild{        TextView tv;    }}

2.2.6 MainActivity.java

package com.yds.example;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import android.app.Activity;import android.os.Bundle;import android.widget.ExpandableListView;public class MainActivity extends Activity {    //声明一个可伸展的列表视图对象    private ExpandableListView expandlist;    //声明并初始化一个组集合对象,该集合时一个一维数组    private List<Map<String, Object>>groupList = new ArrayList<Map<String,Object>>();    //声明一个子元素集合对象,该集合是一个数组链表    private List<List<Map<String, Object>>>childList = new ArrayList<List<Map<String,Object>>>();    //声明一个子元素集合对象    private List<Map<String, Object>>child;    //声明一个map对象    private Map<String, Object>map;    //组元素值    private String[] armTypes = new String[]{            "WORD", "EXCEL", "EMAIL", "PPT"    };    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        //加载布局        setContentView(R.layout.activity_main);        //给组赋值        for (int i = 0; i < armTypes.length; i++) {            //每次都要初始化map对象            map = new HashMap<String, Object>();            //将组值放入key为Group的map中            map.put("Group", armTypes[i]);            //将map添加到组集合中            groupList.add(map);        }        //给每组的子元素赋值        for (int j = 0; j < 4; j++) {            //每次初始化子集合对象。该对象是一个一维数组            child = new ArrayList<Map<String,Object>>();            //每个组下面有25个子元素            for (int i = 0; i < 25; i++) {                //初始化map对象                map = new HashMap<String, Object>();                //将子元素的值放入key值为Child的map中                map.put("Child", "this is "+i+" example");                //将map添加到一维数组中                child.add(map);            }            //将一维数组添加到集合中            childList.add(child);        }        //可伸展的列表视图绑定ID        expandlist = (ExpandableListView) findViewById(R.id.expandlist);        //声明并初始化一个adapter        MyExpandableListAdapter adapter = new MyExpandableListAdapter(MainActivity.this,groupList,childList);        //可伸展的列表视图加载adapter        expandlist.setAdapter(adapter);    }}

三、结果截图:
这里写图片描述

0 0