开发过程中有个需求,要做出一个折叠列表布局,每个列表条目下还有可以三图一行的列表,分析界面后,发现这个可以用现有的控件ExpanadableListView和GridView组合嵌套来实现,即ExpandableListView来战展示标题数据,gridview来展示内部图片,照着这个思路,很快就实现出来了,这里做一下整理归纳。
我们先看一下实际效果
没展开前,初始状态,
点击,展开。
下面谈谈实现流程
1.首先在主界面XML文件里放一个ExpandableListView,这里因为我们要自己加入箭头符号,所以将background设为
null。
<ExpandableListView
android:id="@+id/main_elv"
android:layout_width="match_parent"
android:groupIndicator="@null"
android:dividerHeight="1px"
android:divider="#26000000"
android:layout_height="match_parent"/>
2.这里我们先撸一个继承于GridView的自定义gridview来适应ExpandableListView,否则嵌套后GrdiView会出现不能滑动的bug。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
3.我们来画一级列表item_group的xml布局。
没什么复杂的东西,就是个ImageView和TextView,注意好间距,字体大小之类的就可以。
item_group.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/group_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_group_open_normal"/>
<TextView
android:id="@+id/group_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="创建的文集"
android:layout_marginLeft="7dp"
/>
</LinearLayout>
4.接下来画二级列表的布局item_child.xml,这里只有一个我们自定义的gridView,我们将它设置横向三个元素。
item_child.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.fantasychong.expandablelistviewgridview0228.MyGridView
android:id="@+id/child_gv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="3"
android:paddingLeft="13dp"
android:paddingRight="13dp"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
/>
</LinearLayout>
5.接下来画gridview里每个元素的布局item_gv.xml,这里就一张图片。
item_gv.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/gv_iv"
android:layout_width="150dp"
android:layout_height="200dp"
android:scaleType="centerCrop"
/>
</android.support.constraint.ConstraintLayout>
6.接下来比较重要的一步,我们要构建ExpandableListView的适配器ExpandableListAdapter
让ExpandableListAdapter继承BaseExpandableListAdapter实现一串方法,其中有个重要的方法,返回二级列表的item个数,因为只有一个gridView,所以我们手动给它返回1,否则会有多个gridview出现。
//返回二级列表的item个数,因为这里只有一个GridView,所以我们手动给它赋值1
@Override
public int getChildrenCount(int groupPosition) {
return 1;
}
在getGroupView里,获取item_group.xml中的控件,当isExpand时,给imageview设置向下的图标,反之设置向上的图标。
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView== null){
convertView= LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_group, null);
}
ImageView arrow= convertView.findViewById(R.id.group_arrow);
TextView title= convertView.findViewById(R.id.group_title);
if (isExpanded){
arrow.setImageResource(R.drawable.ic_group_open_normal);
}else {
arrow.setImageResource(R.drawable.ic_group_close_normal);
}
title.setText(groupList.get(groupPosition));
return convertView;
}
在getChildView里,我们在手动撸一个gridview的适配器GridViewAdapter,在这里给gridview设置setAdapter。
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView== null){
convertView= LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_child, null);
}
gv= convertView.findViewById(R.id.child_gv);
MyGridViewAdapter adapter= new MyGridViewAdapter(itemList.get(groupPosition));
gv.setAdapter(adapter);
return convertView;
}
注意各个list的传递,别错乱了。
ExpandableListAdapter.java(内部含GridViewAdapter)
class ExpandableListAdapter extends BaseExpandableListAdapter{
private MyGridView gv;
private List<String> groupList;
private List<List<Integer>> itemList;
public ExpandableListAdapter(List<String> groupList, List<List<Integer>> itemList) {
this.groupList= groupList;
this.itemList= itemList;
}
//返回一级列表的item个数
@Override
public int getGroupCount() {
return groupList.size();
}
//返回二级列表的item个数,因为这里只有一个GridView,所以我们手动给它赋值1
@Override
public int getChildrenCount(int groupPosition) {
return 1;
}
//返回一级列表的position
@Override
public Object getGroup(int groupPosition) {
return groupList.get(groupPosition);
}
//返回二级列表的position
@Override
public Object getChild(int groupPosition, int childPosition) {
return itemList.get(groupPosition).get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView== null){
convertView= LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_group, null);
}
ImageView arrow= convertView.findViewById(R.id.group_arrow);
TextView title= convertView.findViewById(R.id.group_title);
if (isExpanded){
arrow.setImageResource(R.drawable.ic_group_open_normal);
}else {
arrow.setImageResource(R.drawable.ic_group_close_normal);
}
title.setText(groupList.get(groupPosition));
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView== null){
convertView= LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_child, null);
}
gv= convertView.findViewById(R.id.child_gv);
MyGridViewAdapter adapter= new MyGridViewAdapter(itemList.get(groupPosition));
gv.setAdapter(adapter);
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
class MyGridViewAdapter extends BaseAdapter{
private List<Integer> itemGridList3= new ArrayList<>();
private ImageView pic;
public MyGridViewAdapter(List<Integer> itemGridList3) {
this.itemGridList3 = itemGridList3;
}
@Override
public int getCount() {
return itemGridList3.size();
}
@Override
public Object getItem(int position) {
return itemGridList3.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView== null){
convertView= LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_gv, null);
}
pic= convertView.findViewById(R.id.gv_iv);
pic.setImageResource(itemGridList3.get(position));
return convertView;
}
}
}
7.最后在MainActivity给各list添加下固定数据,设置Adapter即可。
/**
* 初始化数据
*/
private void initData() {
groupList.add("创建的文集");
groupList.add("收藏的文集和杂志");
itemGridList.add(R.mipmap.ic_launcher);
for (int i= 0; i< 5; i++){
itemGridList2.add(R.mipmap.ic_launcher_round);
itemGridList2.add(R.mipmap.ic_launcher_round);
itemGridList2.add(R.mipmap.ic_launcher_round);
}
itemList.add(itemGridList);
itemList.add(itemGridList2);
ExpandableListAdapter adapter= new ExpandableListAdapter(groupList, itemList);
elv.setAdapter(adapter);
}
至此全部完成。