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="@drawable/ic_guide_listview_down"
        android:contentDescription="@null"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginRight="16sp"
        android:layout_alignParentRight="true"/>
    

</RelativeLayout>

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="@drawable/delete" />

</RelativeLayout>

自定义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 = new ArrayList<ParentObj>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		createGroupData();
		
		createChildData();
		
		expandableListView = (ExpandableListView) findViewById(R.id.expandable_list_view_id);
		customerAdapter = new CustomerAdapter(listData, this);
		expandableListView.setAdapter(customerAdapter);
		expandableListView.setGroupIndicator(null);
		
		expandableListView.setOnGroupExpandListener(new OnGroupExpandListener() {
			
			@Override
			public void onGroupExpand(int groupPosition) {
				for (int i = 0; i < customerAdapter.getGroupCount(); i ++) {
					if (i != groupPosition) {
						expandableListView.collapseGroup(i);
					}
				}
			}
		});
		
		expandableListView.setOnChildClickListener(new OnChildClickListener() {
			
			@Override
			public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
				Toast.makeText(MainActivity.this, listData.get(groupPosition).getChilds().get(childPosition).getcName(), Toast.LENGTH_LONG).show();
				return true;
			}
		});
	}

	private void createGroupData() {
		ParentObj p1 = new ParentObj();
		p1.setpName("HP");
		listData.add(p1);

		ParentObj p2 = new ParentObj();
		p2.setpName("DELL");
		listData.add(p2);

		ParentObj p3 = new ParentObj();
		p3.setpName("Lenovo");
		listData.add(p3);

		ParentObj p4 = new ParentObj();
		p4.setpName("Sony");
		listData.add(p4);

		ParentObj p5 = new ParentObj();
		p5.setpName("HCL");
		listData.add(p5);

		ParentObj p6 = new ParentObj();
		p6.setpName("Samsung");
		listData.add(p6);
	}

	private void createChildData() {
		// preparing laptops collection(child)
		String[] hpModels = { "HP Pavilion G6-2014TX", "ProBook HP 4540", "HP Envy 4-1025TX" };
		String[] hclModels = { "HCL S2101", "HCL L2102", "HCL V2002" };
		String[] lenovoModels = { "IdeaPad Z Series", "Essential G Series", "ThinkPad X Series", "Ideapad Z Series" };
		String[] sonyModels = { "VAIO E Series", "VAIO Z Series", "VAIO S Series", "VAIO YB Series" };
		String[] dellModels = { "Inspiron", "Vostro", "XPS" };
		String[] samsungModels = { "NP Series", "Series 5", "SF Series" };
		
		for (ParentObj p : listData) {
			if (p.getpName().equals("HP")) {
				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
				for (int i = 0; i < hpModels.length; i ++) {
					ChildObj cObj = new ChildObj();
					cObj.setcName(hpModels[i]);
					clists.add(cObj);
				}
				p.setChilds(clists);
			} else if (p.getpName().equals("DELL")) {
				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
				for (int i = 0; i < dellModels.length; i ++) {
					ChildObj cObj = new ChildObj();
					cObj.setcName(dellModels[i]);
					clists.add(cObj);
				}
				p.setChilds(clists);
			} else if (p.getpName().equals("Lenovo")) {
				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
				for (int i = 0; i < lenovoModels.length; i ++) {
					ChildObj cObj = new ChildObj();
					cObj.setcName(lenovoModels[i]);
					clists.add(cObj);
				}
				p.setChilds(clists);
			} else if (p.getpName().equals("Sony")) {
				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
				for (int i = 0; i < sonyModels.length; i ++) {
					ChildObj cObj = new ChildObj();
					cObj.setcName(sonyModels[i]);
					clists.add(cObj);
				}
				p.setChilds(clists);
			} else if (p.getpName().equals("HCL")) {
				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
				for (int i = 0; i < hclModels.length; i ++) {
					ChildObj cObj = new ChildObj();
					cObj.setcName(hclModels[i]);
					clists.add(cObj);
				}
				p.setChilds(clists);
			} else {
				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
				for (int i = 0; i < samsungModels.length; i ++) {
					ChildObj cObj = new ChildObj();
					cObj.setcName(samsungModels[i]);
					clists.add(cObj);
				}
				p.setChilds(clists);
			}
		}
	}
}

class ParentObj {
	private String pName;
	private ArrayList<ChildObj> childs = new ArrayList<ChildObj>();

	public String getpName() {
		return pName;
	}

	public void setpName(String pName) {
		this.pName = pName;
	}

	public ArrayList<ChildObj> getChilds() {
		return childs;
	}

	public void setChilds(ArrayList<ChildObj> childs) {
		this.childs.clear();
		this.childs.addAll(childs);
	}
}

class ChildObj {
	private String cName;

	public String getcName() {
		return cName;
	}

	public void setcName(String cName) {
		this.cName = cName;
	}
}

源码

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



Android:ExpandableListView使用,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。