今天休息时,我在读一本书,包着书皮的缘由,项目经理不知我在读什么,遂问,你读什么书,我随口道“biancheng”。项目经理听罢,满面笑容,旋即对他一侧的一个人(也是我的同事)讲,你看人家知道在休息时间补充能量,你只知道玩手机,差距就是这样一点一点落下来的!我当时偷笑,委实只能这样了,我是在读“biancheng”,只不过该书的作者是沈从文。
言归正传,项目中需要用到ExpandableListView,自己写了一个Demo,将它记录于此。
先看看主要的XML文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="24sp"
android:text="@string/the_two_provinces_linkage" />
<!-- 两个自定义的expandablelistview控件 -->
<com.example.expandablelistviewtest.ScrollExpandableListView
android:id="@+id/provinceList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:childDivider="@drawable/child_bg" />
<com.example.expandablelistviewtest.ScrollExpandableListView
android:id="@+id/cityList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:childDivider="@drawable/child_bg" />
</LinearLayout>
</ScrollView>
</LinearLayout>
我在布局中使用了“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<String> provinceGroupData;// 定义省级组数据
private ArrayList<ArrayList<String>> provinceChildrenData;// 定义省级组中的子数据
private ArrayList<String> cityGroupData;// 定义市级组数据
private ArrayList<ArrayList<String>> cityChildrenData;// 定义市级组数据中的子数据
private HashMap<String, ArrayList<String>> provinceToCityMap;// 创建省市的键值对
public ArrayList<String> getProvinceGroupData() {
provinceGroupData = new ArrayList<String>();
provinceGroupData.add("省级名称");
return provinceGroupData;
}
public ArrayList<ArrayList<String>> getProvinceChildrenData() {
provinceChildrenData = new ArrayList<ArrayList<String>>();
ArrayList<String> provinceList = new ArrayList<String>();
provinceList.add("北京市");
provinceList.add("上海市");
provinceList.add("广东省");
provinceList.add("浙江省");
provinceList.add("江苏省");
provinceList.add("湖北省");
provinceList.add("山西省");
provinceList.add("河北省");
provinceChildrenData.add(provinceList);
return provinceChildrenData;
}
public ArrayList<String> getCityGroupData() {
cityGroupData = new ArrayList<String>();
cityGroupData.add("市级名称");
return cityGroupData;
}
public ArrayList<ArrayList<String>> getcityChildrenData() {
cityChildrenData = new ArrayList<ArrayList<String>>();
ArrayList<String> beijingList = new ArrayList<String>();
beijingList.add("海淀区");
beijingList.add("丰台区");
beijingList.add("昌平区");
beijingList.add("密云县");
cityChildrenData.add(beijingList);
ArrayList<String> shanghaiList = new ArrayList<String>();
shanghaiList.add("嘉定区");
shanghaiList.add("浦东新区");
cityChildrenData.add(shanghaiList);
ArrayList<String> guangdongList = new ArrayList<String>();
guangdongList.add("广州市");
guangdongList.add("珠海市");
guangdongList.add("佛山市");
guangdongList.add("中山市");
cityChildrenData.add(guangdongList);
ArrayList<String> zhejiangList = new ArrayList<String>();
zhejiangList.add("杭州市");
zhejiangList.add("宁波市");
zhejiangList.add("嘉兴市");
cityChildrenData.add(zhejiangList);
ArrayList<String> jiangsuList = new ArrayList<String>();
jiangsuList.add("南京市");
jiangsuList.add("徐州市");
jiangsuList.add("扬州市");
cityChildrenData.add(jiangsuList);
ArrayList<String> hubeiList = new ArrayList<String>();
hubeiList.add("武汉市");
hubeiList.add("宜昌市");
hubeiList.add("荆门市");
hubeiList.add("黄冈市");
cityChildrenData.add(hubeiList);
ArrayList<String> shanxiList = new ArrayList<String>();
shanxiList.add("太原市");
shanxiList.add("大同市");
shanxiList.add("阳泉市");
cityChildrenData.add(shanxiList);
ArrayList<String> hebeiList = new ArrayList<String>();
hebeiList.add("石家庄市");
hebeiList.add("唐山市");
hebeiList.add("保定市");
cityChildrenData.add(hebeiList);
return cityChildrenData;
}
public HashMap<String, ArrayList<String>> getProvinceAndCity() {
ArrayList<ArrayList<String>> cityChildrenList = getcityChildrenData();
provinceToCityMap = new HashMap<String, ArrayList<String>>();
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<String> provinceGroupData;// 定义省级组数据
private ArrayList<ArrayList<String>> provinceChildrenData;// 定义省级组中的子数据
private ArrayList<String> cityGroupData;// 定义市级组数据
private ArrayList<ArrayList<String>> 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<String>>();
ArrayList<String> 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<String> groupList;
private ArrayList<ArrayList<String>> childList;
private LayoutInflater layoutInflater;
// 定义一个两个长度的数组,存放点中条目的组下标和子下标
private int[] index = new int[2];
private String groupContent;
public ScrollExpandableListAdapter(Context context,
ArrayList<String> groupList,
ArrayList<ArrayList<String>> 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 version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ddd"
android:gravity="center" >
<RelativeLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:paddingRight="10dp" >
<TextView
android:id="@+id/groupName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="@string/group_name"
android:textSize="20sp" />
<TextView
android:id="@+id/groupContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/groupPic"
android:textSize="20sp" />
<ImageView
android:id="@id/groupPic"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/arrow" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:layout_below="@id/layout"
android:background="#ccc" />
</RelativeLayout>
子XML:
<?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="match_parent"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<TextView
android:id="@+id/childContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/check"
android:text="BBB"
android:textSize="20sp" />
<CheckBox
android:id="@id/check"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@drawable/checked"
android:button="@null"
android:visibility="gone" />
</RelativeLayout>
兴许需要讲一下设置ExpandableListView的子Item的分割线的问题,先前用“setChildDivider(null);这个方法来着,但是会报如下空指针错误:
我还不知道这句代码应写在何处,知道的朋友请告诉一下我。
我只好写一个XML文件来代替了,如下:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<!-- 设置ExpandableListView的Child分割线为透明 -->
<!-- <solid android:color="#0000" /> -->
<!-- 设置ExpandableListView的分割线为红色 -->
<solid android:color="#f00" />
</shape>
</item>
</layer-list>
设置成透明即可实现没有分割线的效果,为了直观些,此处我改为了红色。
事实上就这段Demo而言,完全可以做成一个ExpandableListView的,此处用了两个,是我在项目开发中另有用途。
最后看一下效果图吧:
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。