用ExpandableListView做省市二级联动

    今天休息时,我在读一本书,包着书皮的缘由,项目经理不知我在读什么,遂问,你读什么书,我随口道“biancheng”。项目经理听罢,满面笑容,旋即对他一侧的一个人(也是我的同事)讲,你看人家知道在休息时间补充能量,你只知道玩手机,差距就是这样一点一点落下来的!我当时偷笑,委实只能这样了,我是在读“biancheng”,只不过该书的作者是沈从文。

10年积累的成都做网站、成都网站建设经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先制作网站后付款的网站建设流程,更有邻水免费网站建设让你可以放心的选择与我们合作。

    言归正传,项目中需要用到ExpandableListView,自己写了一个Demo,将它记录于此。

    先看看主要的XML文件:



    

        

            

            

            

            
        
    

    我在布局中使用了“ScrollView”,防止一页内容过多,手机屏幕显示不下,那么,问题就来了:ScrollView会和ExpandableListView造成冲突。所以我又自定义了一个叫做“ScrollExpandableListView”的控件,代码如下:

package com.example.expandablelistviewtest;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ExpandableListView;

public class ScrollExpandableListView extends ExpandableListView {

	public ScrollExpandableListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	/* 在ScrollView中嵌套使用ExpandableListView,ExpandableListView只会显示一行多一点。
	两者进行嵌套,即会发生冲突.需要重写OnMesure,对ListView或者GridView同样适用*/
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		
		int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
				MeasureSpec.AT_MOST);
		super.onMeasure(widthMeasureSpec, expandSpec);

	}

}

     同样做了一些有关省市的模拟数据:

package com.example.expandablelistviewtest;

import java.util.ArrayList;
import java.util.HashMap;

public class ProvinceData {

	private ArrayList provinceGroupData;// 定义省级组数据
	private ArrayList> provinceChildrenData;// 定义省级组中的子数据
	private ArrayList cityGroupData;// 定义市级组数据
	private ArrayList> cityChildrenData;// 定义市级组数据中的子数据
	private HashMap> provinceToCityMap;// 创建省市的键值对

	public ArrayList getProvinceGroupData() {

		provinceGroupData = new ArrayList();
		provinceGroupData.add("省级名称");

		return provinceGroupData;

	}

	public ArrayList> getProvinceChildrenData() {

		provinceChildrenData = new ArrayList>();
		ArrayList provinceList = new ArrayList();
		provinceList.add("北京市");
		provinceList.add("上海市");
		provinceList.add("广东省");
		provinceList.add("浙江省");
		provinceList.add("江苏省");
		provinceList.add("湖北省");
		provinceList.add("山西省");
		provinceList.add("河北省");
		provinceChildrenData.add(provinceList);

		return provinceChildrenData;

	}

	public ArrayList getCityGroupData() {

		cityGroupData = new ArrayList();
		cityGroupData.add("市级名称");

		return cityGroupData;

	}

	public ArrayList> getcityChildrenData() {

		cityChildrenData = new ArrayList>();

		ArrayList beijingList = new ArrayList();
		beijingList.add("海淀区");
		beijingList.add("丰台区");
		beijingList.add("昌平区");
		beijingList.add("密云县");
		cityChildrenData.add(beijingList);

		ArrayList shanghaiList = new ArrayList();
		shanghaiList.add("嘉定区");
		shanghaiList.add("浦东新区");
		cityChildrenData.add(shanghaiList);

		ArrayList guangdongList = new ArrayList();
		guangdongList.add("广州市");
		guangdongList.add("珠海市");
		guangdongList.add("佛山市");
		guangdongList.add("中山市");
		cityChildrenData.add(guangdongList);

		ArrayList zhejiangList = new ArrayList();
		zhejiangList.add("杭州市");
		zhejiangList.add("宁波市");
		zhejiangList.add("嘉兴市");
		cityChildrenData.add(zhejiangList);

		ArrayList jiangsuList = new ArrayList();
		jiangsuList.add("南京市");
		jiangsuList.add("徐州市");
		jiangsuList.add("扬州市");
		cityChildrenData.add(jiangsuList);

		ArrayList hubeiList = new ArrayList();
		hubeiList.add("武汉市");
		hubeiList.add("宜昌市");
		hubeiList.add("荆门市");
		hubeiList.add("黄冈市");
		cityChildrenData.add(hubeiList);

		ArrayList shanxiList = new ArrayList();
		shanxiList.add("太原市");
		shanxiList.add("大同市");
		shanxiList.add("阳泉市");
		cityChildrenData.add(shanxiList);

		ArrayList hebeiList = new ArrayList();
		hebeiList.add("石家庄市");
		hebeiList.add("唐山市");
		hebeiList.add("保定市");
		cityChildrenData.add(hebeiList);

		return cityChildrenData;

	}

	public HashMap> getProvinceAndCity() {

		ArrayList> cityChildrenList = getcityChildrenData();
		
		provinceToCityMap = new HashMap>();
		for (int i = 0; i < provinceChildrenData.get(0).size(); i++) {
		
			provinceToCityMap.put(provinceChildrenData.get(0).get(i),
					cityChildrenList.get(i));
		}

		return provinceToCityMap;

	}
}

    接下来是主要的一个类:

package com.example.expandablelistviewtest;

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;

public class ExpandableListViewTest extends Activity {

	private ScrollExpandableListView proviceList;
	private ScrollExpandableListView cityList;
	private ArrayList provinceGroupData;// 定义省级组数据
	private ArrayList> provinceChildrenData;// 定义省级组中的子数据
	private ArrayList cityGroupData;// 定义市级组数据
	private ArrayList> cityChildrenData;// 定义市级组数据中的子数据
	private ProvinceData provinceData;
	// 定义一个两个长度的数组,存放点中条目的组下标和子下标
	private int[] provinceIndex = new int[2];
	private int[] cityIndex = new int[2];

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_expandable_list_view_test);
		provinceIndex[0] = -1;
		provinceIndex[1] = -1;
		provinceData = new ProvinceData();
		provinceGroupData = provinceData.getProvinceGroupData();
		provinceChildrenData = provinceData.getProvinceChildrenData();
		proviceList = (ScrollExpandableListView) findViewById(R.id.provinceList);
		//去掉ExpandableListView默认的箭头,我的手机貌似不用这一句也没有默认的箭头,谁能告诉我怎么回事…… 
		proviceList.setGroupIndicator(null);
		final ScrollExpandableListAdapter provinceAdapter = new ScrollExpandableListAdapter(
				this, provinceGroupData, provinceChildrenData, provinceIndex);		
		proviceList.setAdapter(provinceAdapter);
		cityList = (ScrollExpandableListView) findViewById(R.id.cityList);
		cityGroupData = provinceData.getCityGroupData();

		proviceList.setOnChildClickListener(new OnChildClickListener() {

			@Override
			public boolean onChildClick(ExpandableListView parent, View v,
					int groupPosition, int childPosition, long id) {
				// Expandablelistview 点击子条目后收起列表
				proviceList.collapseGroup(groupPosition);
				provinceIndex[0] = groupPosition;
				provinceIndex[1] = childPosition;
				cityIndex[0] = -1;
				cityIndex[1] = -1;
				String provinceName = provinceChildrenData.get(0).get(childPosition);

					cityList.setVisibility(View.VISIBLE);
					cityList.setGroupIndicator(null);
					cityChildrenData = new ArrayList>();
					ArrayList cityName = provinceData.getProvinceAndCity().get(
							provinceName);
					cityChildrenData.add(cityName);
					ScrollExpandableListAdapter cityAdapter = new ScrollExpandableListAdapter(
							ExpandableListViewTest.this, cityGroupData, cityChildrenData,cityIndex);
					cityList.setAdapter(cityAdapter);
					cityList.setOnChildClickListener(new OnChildClickListener() {
						
						@Override
						public boolean onChildClick(ExpandableListView parent, View v,
								int groupPosition, int childPosition, long id) {
							cityIndex[0] = groupPosition;
							cityIndex[1] = childPosition;
							cityList.collapseGroup(groupPosition);
							return false;
						}
					});

				return false;
			}
		});
	}

}

    最重要的构造器:

package com.example.expandablelistviewtest;

import java.util.ArrayList;

import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;

public class ScrollExpandableListAdapter extends
		BaseExpandableListAdapter {

	private Context context;
	private ArrayList groupList;
	private ArrayList> childList;
	private LayoutInflater layoutInflater;
	// 定义一个两个长度的数组,存放点中条目的组下标和子下标
	private int[] index = new int[2];
	private String groupContent;

	public ScrollExpandableListAdapter(Context context,
			ArrayList groupList,
			ArrayList> childList, int[] index) {
		this.context = context;
		this.groupList = groupList;
		this.childList = childList;
		this.index = index;
		layoutInflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

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

	}

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

	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		ChildViewHolder cHolder = new ChildViewHolder();
		if (convertView == null) {
			convertView = layoutInflater.inflate(R.layout.item_child, null);
			cHolder.childContent = (TextView) convertView
					.findViewById(R.id.childContent);
			cHolder.childCheck = (CheckBox) convertView
					.findViewById(R.id.check);
			convertView.setTag(cHolder);
		} else {
			cHolder = (ChildViewHolder) convertView.getTag();
		}

		cHolder.childContent.setText(childList.get(groupPosition).get(
				childPosition));
		if (index[0] == groupPosition && index[1] == childPosition) {
			cHolder.childCheck.setVisibility(View.VISIBLE);
		} else {
			cHolder.childCheck.setVisibility(View.INVISIBLE);
		}
		return convertView;
	}

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

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

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

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

	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		GroupViewHolder gHolder = new GroupViewHolder();
		if (convertView == null) {
			convertView = layoutInflater.inflate(R.layout.item_group, null);
			gHolder.groupName = (TextView) convertView
					.findViewById(R.id.groupName);
			gHolder.groupContent = (TextView) convertView
					.findViewById(R.id.groupContent);
			gHolder.groupPic = (ImageView) convertView
					.findViewById(R.id.groupPic);
			convertView.setTag(gHolder);
		} else {
			gHolder = (GroupViewHolder) convertView.getTag();
		}
		//首次的话用户没有选择省列表中的子项目,组内容中是没有数据的
		if (index[0] != -1 && index[1] != -1) {
			groupContent = childList.get(index[0]).get(index[1]);
		} else {
			groupContent = "";
		}
		gHolder.groupName.setText(groupList.get(groupPosition));
		gHolder.groupPic.setBackgroundResource(R.drawable.arrow);
		if (!TextUtils.isEmpty(groupContent)) {
			gHolder.groupContent.setText(groupContent);
		}

		return convertView;
	}

	@Override
	public boolean hasStableIds() {
		return false;
	}

	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		index[0] = groupPosition;
		index[1] = childPosition;
		// 实现ChildView点击事件,必须返回true
		return true;
	}

	private class GroupViewHolder {
		TextView groupName;
		TextView groupContent;
		ImageView groupPic;
	}

	private class ChildViewHolder {
		TextView childContent;
		CheckBox childCheck;
	}
}

    组Item与子Item的布局都是自定义的,它们的XML文件分别如下:

    组XML:




    

        

        

        
    

    

    子XML:




    

    

    兴许需要讲一下设置ExpandableListView的子Item的分割线的问题,先前用“setChildDivider(null);这个方法来着,但是会报如下空指针错误:

用ExpandableListView做省市二级联动

我还不知道这句代码应写在何处,知道的朋友请告诉一下我。

    我只好写一个XML文件来代替了,如下:




    
        
            
            
           
           
        
    

    设置成透明即可实现没有分割线的效果,为了直观些,此处我改为了红色。

    事实上就这段Demo而言,完全可以做成一个ExpandableListView的,此处用了两个,是我在项目开发中另有用途。

    最后看一下效果图吧:

用ExpandableListView做省市二级联动

用ExpandableListView做省市二级联动


本文标题:用ExpandableListView做省市二级联动
浏览路径:http://myzitong.com/article/jcodjo.html