首页 > 代码库 > Android:ExpandableListView使用

Android:ExpandableListView使用

前言

眼下回到了工作岗位,第一件事情就是ExpandListView的优化。这里简单的用一个Demo介绍一下ExpandableListView的使用。

简介一下Demo实现的功能,主要是继承BaseExpandableListAdapter来自己定义adapter呈现ExpandableListView数据:
  • 每一个child item有一个TextView和一个ImageView删除标识。
  • 当点击一个child item,弹出Toast提示。
  • child item能够通过点击删除图标来删除。

  • 每次展开特定group时。其它group自己主动收缩。

Demo效果展示:

技术分享


Android实现

创建一个新的Android项目,我将其命名为expandtutorial。

XML布局文件

expandtutorial项目总共须要三个xml布局文件。各自是activity_main.xml。 child_item.xml。 group_item.xml。

activity_main.xml

这个是用来布局ExpandableListView的,内容例如以下:

<RelativeLayout 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" >

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

</RelativeLayout>

group_item.xml

这是用来定义父列表的样式,由一个TextView和一个ImageView构成

<?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="50dp"
    android:background="#ffffff"
    android:orientation="horizontal"
    android:gravity="center_vertical">
    
    <TextView 
        android:id="@+id/group_text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="16dp"
        android:textColor="#808080"
        android:textSize="16sp"
        android:gravity="center_vertical"
        android:layout_alignParentLeft="true"
        android:text="@string/app_name"/>
    
    <ImageView 
        android:id="@+id/group_indicator"
        android:src=http://www.mamicode.com/"@drawable/ic_guide_listview_down">

child_item.xml

这是用来定义孩子列表的样式

<?

xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/child_item_id" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" > <TextView android:id="@+id/child_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:paddingLeft="25dp" /> <ImageView android:id="@+id/child_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:contentDescription="@null" android:src=http://www.mamicode.com/"@drawable/delete" />>

自己定义Adapter

自己定义adapter是继承自BaseExpandableListAdapter。有几个须要注意的地方:
  • 使用静态内部类标识父item和子item的weidget,由于这些控件的id是同样的,这样能够节省掉每次findViewById的时间。
  • 重写(override)isChildSelectable方法,返回true,表示子item是能够点击的。
package com.example.expandtutorial;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class CustomerAdapter extends BaseExpandableListAdapter{
	private ArrayList<ParentObj> datas;
	private Context context;
	
	public CustomerAdapter(ArrayList<ParentObj> datas, Context context) {
		super();
		this.datas = datas;
		this.context = context;
	}

	@Override
	public int getGroupCount() {
		return datas.size();
	}

	@Override
	public int getChildrenCount(int groupPosition) {
		return datas.get(groupPosition).getChilds().size();
	}

	@Override
	public Object getGroup(int groupPosition) {
		return datas.get(groupPosition);
	}

	@Override
	public Object getChild(int groupPosition, int childPosition) {
		return datas.get(groupPosition).getChilds().get(childPosition);
	}

	@Override
	public long getGroupId(int groupPosition) {
		return groupPosition;
	}

	@Override
	public long getChildId(int groupPosition, int childPosition) {
		return childPosition;
	}

	@Override
	// 是否有稳定的id。跟刷新顺序有关
	public boolean hasStableIds() {
		return false;
	}

	@Override
	public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
		ParentViewHolder pviewHolder;
		
		if (convertView == null) {
			convertView = LayoutInflater.from(context).inflate(R.layout.group_item, parent, false);
			pviewHolder = new ParentViewHolder();
			pviewHolder.pTextView = (TextView) convertView.findViewById(R.id.group_text);
			pviewHolder.pImageView = (ImageView) convertView.findViewById(R.id.group_indicator);
			convertView.setTag(pviewHolder);
		}
		
		pviewHolder = (ParentViewHolder)convertView.getTag();
		pviewHolder.pTextView.setTypeface(null, Typeface.BOLD);
		pviewHolder.pTextView.setText(datas.get(groupPosition).getpName());
		
		if (isExpanded) {
			pviewHolder.pImageView.setImageResource(R.drawable.ic_guide_listview_up);
		} else {
			pviewHolder.pImageView.setImageResource(R.drawable.ic_guide_listview_down);
		}
		
		return convertView;
	}

	@Override
	public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
			ViewGroup parent) {
		ChildViewHolder cViewHolder;
		
		if (convertView == null) {
			convertView = LayoutInflater.from(context).inflate(R.layout.child_item, parent, false);
			cViewHolder = new ChildViewHolder();
			cViewHolder.cTextView = (TextView)convertView.findViewById(R.id.child_item);
			cViewHolder.cImageView = (ImageView) convertView.findViewById(R.id.child_delete);
			convertView.setTag(cViewHolder);
		}
		
		cViewHolder = (ChildViewHolder)convertView.getTag();
		cViewHolder.cTextView.setText(datas.get(groupPosition).getChilds().get(childPosition).getcName());
		
		final int gPosition = groupPosition;
		final int cPosition = childPosition;
		cViewHolder.cImageView.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				AlertDialog.Builder builder = new AlertDialog.Builder(context);
				builder.setMessage("Do you want to remove?");
				builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						datas.get(gPosition).getChilds().remove(cPosition);
						notifyDataSetChanged();
					}
				});
				builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.cancel();
					}
				});
				AlertDialog alertDialog = builder.create();
				alertDialog.show();
			}
		});
		
		return convertView;
	}

	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		return true;
	}
	
	static class ParentViewHolder {
		TextView pTextView;
		ImageView pImageView;
	}
	
	static class ChildViewHolder {
		TextView cTextView;
		ImageView cImageView;
	}
}

Activity

我们的主Activity,用来呈现UI效果,这里主要有两个地方须要注意:
  • ExpandableListView须要和自己定义adapter进行绑定,通过setAdapter方法。

  • 默认ExpandableListView带了一个指示箭头。我们自己定义布局是不须要这个指示箭头的。能够使用expandableListView.setGroupIndicator(null);方法将其去掉。
  • 设置setOnGroupExpandListener,当展开一个特定的group时,关闭其它group。
  • 设置setOnChildClickListener,监听孩子点击事件。
package com.example.expandtutorial;

import java.util.ArrayList;

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

public class MainActivity extends Activity {
	private ExpandableListView expandableListView;
	private CustomerAdapter customerAdapter;
	private ArrayList<ParentObj> listData = http://www.mamicode.com/new ArrayList();>

源代码

我将源代码上传到CSDN,大家能够免费下载,欢迎跟帖讨论。源代码地址:http://download.csdn.net/detail/zinss26914/7532205



Android:ExpandableListView使用