ExpandableListView 是什么?
Google官方给出的解释是:
A view that shows items in a vertically scrolling two-level list. This differs from the ListView by allowing two levels: groups which can individually be expanded to show its children. The items come from the ExpandableListAdapter associated with this view.
简单翻译一下就是:
一种用于垂直滚动展示两级列表的视图,和 ListView 的不同之处就是它可以展示两级列表,分组可以单独展开显示子选项。这些选项的数据是通过 ExpandableListAdapter 关联的。这个 ExpandableListAdapter 又是什么呢?和 ListView 使用的 BaseAdapter 差不多,都是用来给 View 提供数据、 实例化子布局的。实际使用的时候实现这个接口就可以了。
我们先看一下实现的效果:
接下来是具体实现方法:
1、建立主布局
和普通的leListView一样,设置好宽度和高度,然后再绑定一个Id即可。
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ExpListView"/>
2、建立分组的布局
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="40dp"
android:background="@color/colorAccent">
<ImageView
android:layout_width="55dp"
android:layout_height="60dp"
android:src="@drawable/aa"
android:id="@+id/image"/>
<TextView
android:id="@+id/label_expand_group"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:text="文本"
android:textColor="@android:color/white"
android:textSize="25sp" />
</LinearLayout>
建立两个控件,ImageView用来放图标,TextView用来放分组标题。
3、建分组子选项的布局
<TextView
android:id="@+id/label_expand_group"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_gravity="center_vertical"
android:gravity="center"
android:textColor="@color/black"
android:text="文本"
android:textSize="20sp" />
我这里的子选项只用了一个TextView来显示文本。
4、建立分组一行数据的实体类
public class Line {
private String text;
private int mageId;
public Line(String text, int mageId) {
this.text = text;
this.mageId = mageId;
}
public String getText() {
return text;
}
public int getMageId() {
return mageId;
}
public void setText(String text) {
this.text = text;
}
public void setMageId(int mageId) {
this.mageId = mageId;
}
}
我这里分组一行只用了两个控件,所以只需要两个变量,然后实现它的get和set方法,为了方便还实现了一个构造方法。
5、建立分组子选项的一行数据的实体类
子选项我没有使用复杂的布局,只有一个TextView来展示数据,所以我使用的是java的String类。
6、建立自定义的数据适配器:
新建一个类,使它继承自 BaseExpandableListAdapter,然后实现它的抽象方法。
public class MyBaseExpandableListAdapter extends BaseExpandableListAdapter {
private List groupArray;//分组
private List<List> childArray;//分组中的子选项
private Context context;
public MyBaseExpandableListAdapter(List groupArray, List<List> childArray, Context context) {
this.groupArray = groupArray;
this.childArray = childArray;
this.context = context;
}
@Override
// 获取分组的个数
public int getGroupCount() {
return groupArray.size();
}
@Override
// 获取指定分组中的子选项的个数
public int getChildrenCount(int groupPosition) {
Log.d(TAG, "getChildrenCount: " + childArray.get(groupPosition).size());
return childArray.get(groupPosition).size();
}
@Override
// 获取指定的分组数据
public Object getGroup(int groupPosition) {
return childArray.get(groupPosition);
}
@Override
// 获取指定分组中的指定子选项数据
public Object getChild(int groupPosition, int childPosition) {
return childArray.get(groupPosition).get(childPosition);
}
@Override
// 获取指定分组的ID, 这个ID必须是唯一的
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
// 获取子选项的ID, 这个ID必须是唯一的
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
// 分组和子选项是否持有稳定的ID, 就是说底层数据的改变会不会影响到它们。
public boolean hasStableIds() {
return true;
}
@Override
// 获取显示指定分组的视图
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
ViewHolder viewHolder;
if (convertView == null) {
viewHolder=new ViewHolder();
convertView = layoutInflater.inflate(R.layout.item_expand_child, null);
viewHolder.textView = convertView.findViewById(R.id.label_expand_group);
viewHolder.imageView = convertView.findViewById(R.id.image);
convertView.setTag(viewHolder);
}
else {
viewHolder= (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(groupArray.get(groupPosition).getText());
viewHolder.imageView.setImageResource(groupArray.get(groupPosition).getMageId());
return convertView;
}
@Override
// 获取显示指定分组中的指定子选项的视图
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater layoutInflater = LayoutInflater.from(context);
convertView = layoutInflater.inflate(R.layout.group_expand_child, null);
viewHolder.textView = convertView.findViewById(R.id.label_expand_group);
convertView.setTag(viewHolder);
} else {
viewHolder= (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(childArray.get(groupPosition).get(childPosition));
return convertView;
}
@Override
// 指定位置上的子元素是否可选中
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
private class ViewHolder {
public TextView textView;
public ImageView imageView;
}
}
7、准备数据
<string-array name="citys">
<item>湖南</item>
<item>内蒙古</item>
<item>浙江</item>
</string-array>
<string-array name="湖南">
<item>长沙</item>
<item>株洲</item>
<item>湘潭</item>
<item>衡阳</item>
<item>邵阳</item>
<item>岳阳</item>
<item>常德</item>
<item>张家界</item>
<item>益阳</item>
<item>郴州</item>
<item>永州</item>
<item>怀化</item>
<item>娄底</item>
<item>湘西</item>
</string-array>
<string-array name="内蒙古">
<item>呼和浩特</item>
<item>包头</item>
<item>乌海</item>
<item>赤峰</item>
<item>呼伦贝尔盟</item>
<item>阿拉善盟</item>
<item>哲里木盟</item>
<item>兴安盟</item>
<item>乌兰察布盟</item>
<item>锡林郭勒盟</item>
<item>巴彦淖尔盟</item>
<item>鄂市</item>
</string-array>
<string-array name="浙江">
<item>杭州</item>
<item>宁波</item>
<item>温州</item>
<item>嘉兴</item>
<item>湖州</item>
<item>绍兴</item>
<item>金华</item>
<item>衢州</item>
<item>舟山</item>
<item>台州</item>
<item>丽水</item>
</string-array>
这里我定义了四个数组,分别是分组名和分组子选项要显示的内容。
并且准备好图片资源
8、组合数据并调用数据适配器
public class ExpListviewActivity extends AppCompatActivity {
private static final String TAG = "ExpListviewActivity";
private ExpandableListView expandableListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exp_listview);
//从资源文件中分别获取数据到数组
String[] groupStrings = getResources().getStringArray(R.array.citys);
int[] images = {R.drawable.aa, R.drawable.bb, R.drawable.cc, R.drawable.dd};
String[] 湖南 = getResources().getStringArray(R.array.湖南);
String[] 内蒙古 = getResources().getStringArray(R.array.内蒙古);
String[] 浙江 = getResources().getStringArray(R.array.浙江);
//将分组子选项通过二维数组组合,便于引用。
String[][] childStrings = {湖南, 内蒙古, 浙江};
//组合分组数据
List groupArray = new ArrayList<>();
for (int i = 0; i < groupStrings.length; i++) {
groupArray.add(new Line(groupStrings[i], images[i]));
}
//用双层循环组合分组子选项的数据
List<List> listChildStrings = new ArrayList<>();
for (int i = 0; i < childStrings.length; i++) {
List 一行 = new ArrayList<>();
for (int j = 0; j < childStrings[i].length; j++) {
一行.add(childStrings[i][j]);
}
listChildStrings.add(一行);
}
//实例化ExpandableListView
expandableListView = findViewById(R.id.ExpListView);
//创建数据适配器并调用。
MyBaseExpandableListAdapter myBaseExpandableListAdapter =
new MyBaseExpandableListAdapter(groupArray, listChildStrings, ExpListviewActivity.this);
expandableListView.setAdapter(myBaseExpandableListAdapter);
//分组的子选项点击事件
expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Toast.makeText(ExpListviewActivity.this, groupPosition+"组"+childPosition+"个,从0开始数", Toast.LENGTH_SHORT).show();
return false;
}
});
//分组的点击事件
expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Toast.makeText(ExpListviewActivity.this,groupPosition+"组" , Toast.LENGTH_SHORT).show();
return false;
}
});
}
}
Comments | NOTHING