目录
1. XML代码
2. ExpandableListView的使用
3. ExpandableListAdapter的使用
4. 数据观察者的使用
5. 案例代码一览
ExpandableListView(可扩展/可折叠列表视图)是一种多功能的高级控件,每个子项都可以展开一个孙子列表。点击一个分组(子项),即可展开该分组下的孙子列表;再次点击该分组,即可收起该分组下的孙子项列表。
1. XML代码
<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
2. ExpandableListView的使用
可折叠列表视图的常用方法说明:
- setAdapter:设置适配器。适配器类型为ExpandableListAdapter。
- expandGroup:展开指定分组。
- collapseGroup:收起指定分组。
- isGroupExpanded:判断指定分组是否展开。
- setSelectedGroup:设置选中的分组。
- setSelectedChild:设置选中的孙子项。
- setGroupIndicator:设置指定分组的指示图像。
- setChildIndicator:设置指定孙子项的指示图像。
- setOnGroupExpandListener:设置分组展开监听器。需实现接口 OnGroupExpandListener的onGroupExpand方法,该方法在点击展开分组时触发。
- setOnGroupCollapseListener:设置分组收起监听器。需实现接口 OnGroupCollapseListener的onGroupCollapse方法,该方法在点击收起分组时触发。
- setOnGroupClickListener:设置分组点击监听器。需实现接口 OnGroupClickListener 的onGroupClick方法,该方法在点击分组时触发。
- setOnChildClickListener:设置孙子项点击监听器。需实现接口 OnChildClickListener 的onChildClick方法,该方法在点击孙子项时触发。
3. ExpandableListAdapter的使用
可折叠列表视图拥有专属的适配器ExpandableListAdapter(可折叠列表适配器)。
下面是该适配器经常要重写的5个方法:
- getGroupCount:获取分组的个数。
- getChildrenCount:获取孙子项的个数。
- getGroupView:获取指定分组的视图。
- getChildView:获取指定孙子项的视图。
- isChildSelectable:判断孙子项是否允许选择。
全部方法使用说明如下所示:
class MyAdapter implements ExpandableListAdapter {
DataSetObserver dataSetObserver;
public MyAdapter(){
//构造方法,可以在参数中进行数据传入
}
//注册数据观察者
public void registerDataSetObserver(DataSetObserver dataSetObserver) {
this.dataSetObserver=dataSetObserver;
}
//注销数据观察者
public void unregisterDataSetObserver(DataSetObserver dataSetObserver) {
dataSetObserver=null;
}
//返回父项的数量,即可展开列表中的组数
public int getGroupCount() {
return 0;
}
//返回特定组(父项)中子项的数量
public int getChildrenCount(int i) {
return 0;
}
//返回指定位置的父项对象
public Object getGroup(int i) {
return null;
}
//返回指定位置的子项对象
public Object getChild(int i, int i1) {
return null;
}
//返回指定位置的父项的唯一标识符
public long getGroupId(int i) {
return 0;
}
//返回指定位置的子项的唯一标识符
public long getChildId(int i, int i1) {
return 0;
}
//返回一个布尔值,表示适配器的项目是否具有稳定的唯一标识符。如果返回 true,则表示每个项的标识符在数据集的生命周期内保持稳定
public boolean hasStableIds() {
return false;
}
//获取父项的视图
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
return null;
}
//获取子项的视图
public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
return null;
}
//返回一个布尔值,表示特定的子项是否可选
public boolean isChildSelectable(int i, int i1) {
return false;
}
//返回一个布尔值,表示所有的列表项是否可选。一般情况下,如果所有项都是可选的,则返回 true
public boolean areAllItemsEnabled() {
return false;
}
//返回一个布尔值,表示适配器是否为空。
public boolean isEmpty() {
return false;
}
//在父项展开时被调用
public void onGroupExpanded(int i) {
}
//在父项折叠时被调用
public void onGroupCollapsed(int i) {
}
//用于获取子项的组合ID。这在某些情况下可以用于唯一标识某个项。
public long getCombinedChildId(long l, long l1) {
return 0;
}
//用于获取父项的组合ID。这在某些情况下可以用于唯一标识某个项。
public long getCombinedGroupId(long l) {
return 0;
}
}
4. 数据观察者的使用
在Android中,要让DataSetObserver(数据观察者)监听数据,通常需要将它注册到适配器(Adapter)或者数据集(DataSet)上。然后,当数据集的内容发生变化时,DataSetObserver中相应的方法会被自动调用。
//获取控件
ExpandableListView expandableListView=findViewById(R.id.expandableListView);
//创建适配器
MyAdapter myAdapter=new MyAdapter();
//创建数据观察者
DataSetObserver dataSetObserver=new DataSetObserver() {
public void onChanged() {
super.onChanged();
//数据变化时修改UI
}
public void onInvalidated() {
super.onInvalidated();
//数据集无效时调用此方法
}
};
//注册数据观察者
myAdapter.registerDataSetObserver(dataSetObserver);
//设置适配器
expandableListView.setAdapter(myAdapter);
//...数据变化...
//使用数据观察者,调用onChanged方法
myAdapter.dataSetObserver.onChanged();
5. 案例代码一览
<!--activity_main_xml-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<!--group_layout.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="50dp"
android:background="@color/teal_200">
<TextView
android:id="@+id/group_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="group-null"/>
</RelativeLayout>
<!--child_layout.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="30dp"
android:background="@color/purple_700">
<TextView
android:id="@+id/child_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="child-null"/>
</RelativeLayout>
//自定义适配器
class MyAdapter implements ExpandableListAdapter {
ArrayList<View> groupArrayList=null;
ArrayList<ArrayList<View>> childArrayLists=null;
public MyAdapter(ArrayList<View> groupArrayList,ArrayList<ArrayList<View>> childArrayLists){
//构造方法,可以在参数中进行数据传入
this.groupArrayList=groupArrayList;
this.childArrayLists=childArrayLists;
}
//返回父项的数量,即可展开列表中的组数
public int getGroupCount() {
return groupArrayList.size();
}
//返回特定组(父项)中子项的数量
public int getChildrenCount(int i) {
return childArrayLists.get(i).size();
}
//获取父项的视图
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
return groupArrayList.get(i);
}
//获取子项的视图
public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
return childArrayLists.get(i).get(i1);
}
//返回一个布尔值,表示特定的子项是否可选
public boolean isChildSelectable(int i, int i1) {
return false;
}
//...其他方法
}
//MainActivity.java
public class MainActivity extends AppCompatActivity {
@SuppressLint("MissingInflatedId")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//准备参数
ArrayList<View> groupArrayList=new ArrayList<>();
ArrayList<ArrayList<View>> childArrayLists=new ArrayList<>();
for(int i=0;i<10;i++){
//group
View view= LayoutInflater.from(MainActivity.this).inflate(R.layout.group_layout,null);
((TextView)view.findViewById(R.id.group_textView)).setText("group:"+i);
groupArrayList.add(view);
//child
ArrayList<View> childArrayList=new ArrayList<>();
for(int i1=0;i1<6;i1++){
View view1=LayoutInflater.from(MainActivity.this).inflate(R.layout.child_layout,null);
((TextView)view1.findViewById(R.id.child_textView)).setText("child:"+i1);
childArrayList.add(view1);
}
childArrayLists.add(childArrayList);
}
//获取控件
ExpandableListView expandableListView=findViewById(R.id.expandableListView);
//创建适配器
MyAdapter myAdapter=new MyAdapter(groupArrayList,childArrayLists);
//设置适配器
expandableListView.setAdapter(myAdapter);
}
}
tag:ExpandableListView;可扩展列表视图;可折叠列表视图;适配器;Adapter