用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 ArrayListprovinceGroupData;// 定义省级组数据 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 ArrayListprovinceGroupData;// 定义省级组数据 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 ArrayListgroupList; 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);这个方法来着,但是会报如下空指针错误:
我还不知道这句代码应写在何处,知道的朋友请告诉一下我。
我只好写一个XML文件来代替了,如下:
设置成透明即可实现没有分割线的效果,为了直观些,此处我改为了红色。
事实上就这段Demo而言,完全可以做成一个ExpandableListView的,此处用了两个,是我在项目开发中另有用途。
最后看一下效果图吧:
名称栏目:用ExpandableListView做省市二级联动
标题URL:http://pwwzsj.com/article/jcodjo.html