Android ExpandableListView的技巧



前言:

ExpandableListView是可扩展的下拉列表,它的可扩展性在于点击父item可以拉下或收起列表,适用于一些场景的使用,下面介绍的是在Activity中如何使用(如果对ExpandableListView一无所知,建议按照顺序去阅读,遇到问题再看本文)

1、Android中ExpandableListView的使用

网址:http://blog.csdn.net/gyflyx/article/details/6461242

2、[Android UI设计]ExpandableListView详解

网址:http://www.tuicool.com/articles/JjaMnqf 

 

ExpandableListView是Android中可以实现下拉ListView的一个控件,是ListView的子类。

直接上图,就是这么一功能~

    

(点击就会展开,再点击就缩回去)

Android自带的布局不是这样的,这个是自定义了Group和Child的布局。

 

ExpandableListView的使用步骤:
1、在xml中定义一个ExpandableListView
2、在类中定义两个List集合,用于存放Group/Child中的内容,并初始化内容
3、定义ExpandableListView的Adapter,继承BaseExpanableListAdapter
例如:public class MyExpandableAdapter extends BaseExpandableListAdapter 
4、最后给定义好的ExpandableView添加上Adapte

activity_expandable_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorshallowgray">
    <ExpandableListView
        android:id="@+id/ev_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorWhite"
        android:divider="@null"
        android:groupIndicator="@null"
        android:cacheColorHint="#00000000"
        android:listSelector="#00000000" />

</LinearLayout>


adapter_expandlist_group_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="70dp" android:gravity="center_vertical"
    android:paddingLeft="12dp">

    <ImageView
        android:id="@+id/iv_expandlist_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/ic_arrow_right"/>

    <TextView
        android:id="@+id/tv_expandlist_group_name"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center_vertical"
        android:layout_marginLeft="12dp"
        android:textColor="@color/colorBlack"
        android:textSize="20sp"/>

</LinearLayout>


adapter_expandlist_child_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="wrap_content" android:paddingLeft="16dp">

    <com.makeramen.roundedimageview.RoundedImageView
        android:id="@+id/iv_expandlist_child_avatar"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:scaleType="fitCenter"
        android:src="@mipmap/luxun"
        app:riv_oval="true"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="vertical"
        android:paddingLeft="12dp">
        <TextView
            android:id="@+id/tv_expandlist_child_name"
            android:layout_width="match_parent"
            android:layout_height="25dp"
            android:gravity="center_vertical"
            android:textColor="@color/colorRed"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/tv_expandlist_child_content"
            android:layout_width="match_parent"
            android:layout_height="24dp"
            android:textColor="@color/colorLightBlack"
            android:textSize="16dp" />

        <ImageView
            android:id="@+id/iv_expandlist_child_divider"
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:background="@color/colorShallowBlack"/>
    </LinearLayout>

</LinearLayout>


<com.makeramen.roundedimageview.RoundedImageView
    android:id="@+id/iv_expandlist_child_avatar"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:scaleType="fitCenter"
    android:src="@mipmap/luxun"
    app:riv_oval="true"/>

圆形头像可参考:http://blog.csdn.net/heaven_bingwang/article/details/71423146


ExpandableListActivity.java

package com.neon.crm.activity.listview;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.ExpandableListView;
import android.widget.Toast;

import com.neon.crm.R;
import com.neon.crm.adapter.ExpandableListAdapter;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/5/5.
 * ExpandableListActivity
 */

public class ExpandableListActivity extends Activity {

    private ExpandableListView expandableListView;

    //设置组视图的显示文字
    private List<String> group;           //组列表
    private List<List<String>> child;     //子列表
    private List<List<Integer>> logou;     //子列表
    private ExpandableListAdapter adapter;;  //数据适配器

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_expandable_list);
        findViewById();
        ininData();
    }

    public void findViewById(){
        expandableListView = (ExpandableListView) findViewById(R.id.ev_view);
    }
    /**
     * 初始化组、子列表数据
     */
    public void ininData(){
        group = new ArrayList<String>();
        child = new ArrayList<List<String>>();
        logou = new ArrayList<List<Integer>>();
        addInfo("魏",
                new String[]{ "夏侯惇", "甄姬", "许褚", "郭嘉", "司马懿", "杨修" },
                new Integer[]{ R.mipmap.xiahoudun, R.mipmap.zhenji,
                        R.mipmap.xuchu, R.mipmap.guojia,
                        R.mipmap.simayi, R.mipmap.yangxiu }
                ) ;
        addInfo("蜀",
                new String[]{ "马超", "张飞", "刘备", "诸葛亮", "黄月英", "赵云" },
                new Integer[]{ R.mipmap.machao, R.mipmap.zhangfei,
                        R.mipmap.liubei, R.mipmap.zhugeliang,
                        R.mipmap.huangyueying, R.mipmap.zhaoyun }
                ) ;
        addInfo("吴",
                new String[]{ "吕蒙", "陆逊", "孙权", "周瑜", "孙尚香" },
                new Integer[]{ R.mipmap.lvmeng, R.mipmap.luxun, R.mipmap.sunquan,
                        R.mipmap.zhouyu, R.mipmap.sunshangxiang }
                ) ;

        adapter = new ExpandableListAdapter(this,group,child,logou);
        expandableListView.setAdapter(adapter);

        expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                Toast.makeText(
                        ExpandableListActivity.this,
                        "你点击了" + adapter.getChild(groupPosition, childPosition),
                        Toast.LENGTH_SHORT).show();
                return false;
            }
        });
    }
    /**
     * 模拟给组、子列表添加数据
     */
    private void addInfo(String g,String[] c, Integer[] l){
        group.add(g);
        List<String> childitem = new ArrayList<String>();
        List<Integer> logouitem = new ArrayList<Integer>();
        for(int i=0;i<c.length;i++){
            childitem.add(c[i]);
            logouitem.add(l[i]);
        }
        logou.add(logouitem);
        child.add(childitem);
    }
}

ExpandableListAdapter.java

package com.neon.crm.adapter;

import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.neon.crm.R;

import java.util.List;

/**
 * Created by Administrator on 2017/5/5.
 * ExpandableListAdapter
 */

public class ExpandableListAdapter extends  BaseExpandableListAdapter{

    private Context mContext;
    private List<String> mGroup;           //组列表
    private List<List<String>> mChild;     //子列表
    private List<List<Integer>> mLogou;     //子列表

    public ExpandableListAdapter(Context context,List<String> group,List<List<String>> child,
                                 List<List<Integer>> logou){
        this.mContext = context;
        this.mGroup = group;
        this.mChild = child;
        this.mLogou = logou;
    }

    //  获得某个父项
    @Override
    public Object getGroup(int groupPosition) {
        return mGroup.get(groupPosition);
    }

    //  获得某个父项的某个子项
    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return mChild.get(groupPosition).get(childPosition);
    }

    //  获得父项的数量
    @Override
    public int getGroupCount() {
        return mGroup.size();
    }

    //  获得某个父项的子项数目
    @Override
    public int getChildrenCount(int groupPosition) {
        return mChild.get(groupPosition).size();
    }

    //  获得某个父项的id
    @Override
    public long getGroupId(int parentPos) {
        return parentPos;
    }

    //  获得某个父项的某个子项的id
    @Override
    public long getChildId(int parentPos, int childPos) {
        return childPos;
    }

    //  按函数的名字来理解应该是是否具有稳定的id,这个方法目前一直都是返回false,没有去改动过
    @Override
    public boolean hasStableIds() {
        return true;
    }

    //  获得父项显示的view
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {
        View view = convertView;
        GroupHolder holder = null;
        if(view == null){
            holder = new GroupHolder();
            view = LayoutInflater.from(mContext).inflate(R.layout.adapter_expandlist_group_item, null);
            holder.groupName = (TextView)view.findViewById(R.id.tv_expandlist_group_name);
            holder.arrow = (ImageView)view.findViewById(R.id.iv_expandlist_group);
            view.setTag(holder);
        }else{
            holder = (GroupHolder)view.getTag();
        }

        //判断是否已经打开列表
        if(isExpanded){
            holder.arrow.setBackgroundResource(R.mipmap.ic_arrow_down);
        }else{
            holder.arrow.setBackgroundResource(R.mipmap.ic_arrow_right);
        }
        holder.groupName.setText(mGroup.get(groupPosition));

        return view;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {

        View view = convertView;
        ChildHolder holder = null;
        if(view == null){
            holder = new ChildHolder();
            view = LayoutInflater.from(mContext).inflate(R.layout.adapter_expandlist_child_item, null);
            holder.childAvatar = (ImageView)view.findViewById(R.id.iv_expandlist_child_avatar);
            holder.childName = (TextView)view.findViewById(R.id.tv_expandlist_child_name);
            holder.childContent = (TextView)view.findViewById(R.id.tv_expandlist_child_content);
            holder.divider = (ImageView)view.findViewById(R.id.iv_expandlist_child_divider);
            view.setTag(holder);
        }else{
            holder = (ChildHolder)view.getTag();
        }

        if(childPosition == getChildrenCount(groupPosition)-1){
            holder.divider.setVisibility(View.GONE);
        } else {
            holder.divider.setVisibility(View.VISIBLE);
        }

        holder.childAvatar.setImageResource(mLogou.get(groupPosition).get(childPosition));
        holder.childName.setText(mChild.get(groupPosition).get(childPosition));
        holder.childContent.setText(mChild.get(groupPosition).get(childPosition));

        return view;
    }

    //自己定义一个获得文字信息的方法
    TextView getTextView() {
        AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT, 64);
        TextView textView = new TextView(mContext);
            textView.setLayoutParams(lp);
            textView.setGravity(Gravity.CENTER_VERTICAL);
            textView.setPadding(80, 0, 0, 0);
            textView.setTextSize(20);
            textView.setTextColor(Color.BLACK);
        return textView;
    }

    //  子项是否可选中,如果需要设置子项的点击事件,需要返回true
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

    class GroupHolder{
        public TextView groupName;
        public ImageView arrow;
    }

    class ChildHolder{
        public TextView childName,childContent;
        public ImageView childAvatar;
        public ImageView divider;
    }
}

 

有一下几点需要注意的:

1.设置指示器

有人也许会发现效果图中没有默认箭头(指示器),因为我隐藏了啊~


android:groupIndicator="@null",这样就是设置没有指示器,就是默认的.

如果刚刚的代码,没有设置隐藏指示器就是下图的效果:

(这样就很影响美观,不好看。)

2.自定义指示器

隐藏了就要自定义一个指示器了喔。


在ExpandableAdapter中的getGroupView中参数有一个参数是isExpanded,代表当前Group是否已经打开。

关键代码:

//判断是否已经打开列表
        if(isExpanded){
            holder.arrow.setBackgroundResource(R.drawable.dowm_arrow);
        }else{
            holder.arrow.setBackgroundResource(R.drawable.right_arrow);
        }

打开了就返回true,没有打开就返回false。

 

3.默认打开某一个Group

ExpandableListView expandableListView;

...省略获取id得到实例的代码

expandableListView.expandGroup(int)

4.设置每一个item的高度

这个问题困扰了我很久,上面的两个链接也没有明确的说明,于是就百度了半天,终于找出答案了。
但是不知道为什么,要嵌套布局才可以,就是外面一个布局设定高度,里面再设定一个布局也设定高度。然后实际上宽度和高度都是在第二个里设置才有效。

下面是adapter_expandlist_group_item.xml的部分代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="70dp" android:gravity="center_vertical"
    android:paddingLeft="12dp">

    <ImageView
        android:id="@+id/iv_expandlist_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/ic_arrow_right"/>

    <TextView
        android:id="@+id/tv_expandlist_group_name"
        android:layout_width="wrap_content"
        android:layout_height="50dp"



  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值