时间过得很快,转眼年也过完了,在匆匆的岁月长河里总是莫名的心慌,可能时间真的是最残忍的那个,无论你喜或悲、乐与乏,他都持续流逝着,不快不慢。废话不多说,在开工的前一天(昨天)陈闲暇之时写了一个通过expandableListView实现三级列表的demo,昨天写完demo就没时间了,今天写到博客里,算是新年开工第一篇了。
首先看一下效果图:
我们都知道,通过expandableListView可以实现两级列表,那么怎么实现三级列表呢?其实也简单,我们可以通过expandableListView嵌套expandableListView的方式实现。
ExpendableListView
的使用和ListView几乎一样:
- 编写布局文件并获取
ExpendableListView
。 - 自定义适配器继承
BaseExpandableListAdapter。
setAdapter
设置适配器。
下面开始进行实现:
- 编写布局文件并查找控件
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.cui.therelisttestdemo.MainActivity"> <ExpandableListView android:id="@+id/expandable_listView" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
- 自定义
Adapter
继承自BaseExpandableListAdapter,此处因为使用的实expandableListView的嵌套,所以也需要定义两个adapter,
我们分别称之为OuterAdapter和InnerAdapter。
在编写该类之前,我们必须要有我们的实体类。看一下我们定义的国家、省、市实体类Classes,并分别设置他的set和get方法。
/** * 国家实体类 * Created by Administrator on 2018/2/21. */ public class CountyEntity { //国家名 private String name; //国家的省集合 private List<Province> provinces; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Province> getProvinces() { return provinces; } public void setProvinces(List<Province> provinces) { this.provinces = provinces; } /** * 省实体类 */ static class Province{ //省的名称 private String name; //省内的城市集合 private List<City> cities; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<City> getCities() { return cities; } public void setCities(List<City> cities) { this.cities = cities; } } /** * 城市实体类 */ static class City{ //城市名称 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
ok,写完实体类后直接上OuterAdapter和InnerAdapter
的代码。
OuterAdaper:
public class OutAdapter extends BaseExpandableListAdapter { private List<CountyEntity> countyEntities;//国家的集合 private Activity activity;//创建布局使用 //构造方法 public OutAdapter(List<CountyEntity> countyEntities, Activity activity) { if (countyEntities != null) { this.countyEntities = countyEntities; } else countyEntities = new ArrayList<>(); this.activity = activity; } // 组数量 @Override public int getGroupCount() { return countyEntities.size(); } //子View数量 @Override public int getChildrenCount(int i) { return 1; } //获取组对象 @Override public Object getGroup(int i) { return countyEntities.get(i); } //获取子View对象 @Override public Object getChild(int i, int i1) { return countyEntities.get(i).getProvinces().get(i1); } // 组View下标 @Override public long getGroupId(int i) { return i; } //子View下标 @Override public long getChildId(int i, int i1) { return i1; } @Override public boolean hasStableIds() { return false; } //获取组布局 @Override public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) { TextView textView = new TextView(activity); AbsListView.LayoutParams params = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); textView.setLayoutParams(params); textView.setLeft(20); textView.setPadding(90, 15, 10, 15); textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); textView.setText(countyEntities.get(i).getName()); return textView; } //获取子View @Override public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) { AbsListView.LayoutParams params = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); InnerExpandableListView expandableListView = new InnerExpandableListView(activity); expandableListView.setLayoutParams(params); InnerAdapter adapter = new InnerAdapter(countyEntities.get(i).getProvinces(), activity); expandableListView.setAdapter(adapter); expandableListView.setPadding(90, 15, 5, 15); return expandableListView; } @Override public boolean isChildSelectable(int i, int i1) { return true; } }
InerAdapter:
public class InnerAdapter extends BaseExpandableListAdapter { private List<CountyEntity.Province> provinces;.//省的集合 private Activity activity;//创建布局使用 //构造参数 public InnerAdapter(List<CountyEntity.Province> provinces, Activity activity) { if (provinces!=null) { this.provinces = provinces; }else provinces=new ArrayList<>(); this.activity = activity; } //获取外层组个数 @Override public int getGroupCount() { return provinces.size(); } //获取内层组个数 @Override public int getChildrenCount(int i) { return provinces.get(i).getCities().size(); } //获取外层组 @Override public Object getGroup(int i) { return provinces.get(i); } //获取内层数据 @Override public Object getChild(int i, int i1) { return provinces.get(i).getCities().get(i1); } //组下标 @Override public long getGroupId(int i) { return i; } //子View下标 @Override public long getChildId(int i, int i1) { return i1; } //不知道做什么用 @Override public boolean hasStableIds() { return false; } //获取组布局 @Override public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) { TextView textView=new TextView(activity); AbsListView.LayoutParams params=new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); textView.setLayoutParams(params); textView.setPadding(90,15,10,15); textView.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT); textView.setText(provinces.get(i).getName()); return textView; } //获取子View布局 @Override public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) { TextView textView=new TextView(activity); AbsListView.LayoutParams params=new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); textView.setLayoutParams(params); textView.setPadding(110,15,10,15); textView.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT); textView.setText(provinces.get(i).getCities().get(i1).getName()); return textView; } //子View是否可选 @Override public boolean isChildSelectable(int i, int i1) { return true; } }
观察可以发现,OuterAdapter和InnerAdapter的代码几乎全部相同,其中之一的不同是返回的子View不同,在OuterAdapter中子View返回的是我们自定义的一个InnerExpandableListView继承自expandableListView(这里之所以要自定义expandableListView是因为在ListView嵌套ListView的时候发现里边的ListView显示不全,为了全部显示,重写了expandableListView),这就是我们说的expandableListView嵌套expandableListView,通过adapter类返回一个expandableListView实现。还有一个不同那就是在OuterAdapter返回子View个数的时候我们返回的是1,记住,这个 非常关键,因为他具体的显示都交给了子ExpandableListView
,二级条目的目的是为了把子ExpandableListView
显示出来。
下面简单介绍其中几个关键方法
getGroupCount()
:获取一级条目的数量。getChildrenCount()
:获取二级条目的数量。getGroupView()
:获取一级条目的对应布局。getChildView()
:获取二级条目对应的布局。再看一下InnerExpandableListView的写法
public class InnerExpandableListView extends ExpandableListView { public InnerExpandableListView(Context context) { super(context); } public InnerExpandableListView(Context context, AttributeSet attrs) { super(context, attrs); } public InnerExpandableListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //通过此方法重新计算expandableListView的高度,使得里边的expandableListView全部显示 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2 , MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
setAdapter()
设置适配器
public class MainActivity extends AppCompatActivity { private ExpandableListView expandableListView; List<CountyEntity> countyEntities=new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); expandableListView = findViewById(R.id.expandable_listView); initData(); //创建适配器实例,设置适配器 OutAdapter adapter=new OutAdapter(countyEntities,this); expandableListView.setAdapter(adapter); } //创造数据 private void initData() { for (int m=0;m<4;m++) { CountyEntity countyEntity=new CountyEntity(); countyEntity.setName("国家"+m); List<CountyEntity.Province> provinces=new ArrayList<>(); for (int j = 0; j < 6; j++) { CountyEntity.Province province=new CountyEntity.Province(); province.setName("省"+j); List<CountyEntity.City> cities = new ArrayList<>(); for (int i = 0; i < 5; i++) { CountyEntity.City city = new CountyEntity.City(); city.setName("城市" + i); cities.add(city); } province.setCities(cities); provinces.add(province); } countyEntity.setProvinces(provinces); countyEntities.add(countyEntity); } } }