Android学习之ExpandableListView
作者:互联网
什么是ExpandableListView
ExpandableListView是扩展的ListView,继承自ListView;ExpandableListView可以实现点击展开列表,再点击收缩回去的效果。
ExpandableListView的使用
首先需要在主布局文件中声明ExpandableListView;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".TestActivity3"
android:orientation="vertical">
<!--
indicatorLeft:指示符的左边界
indicatorRight: 指示符的右边界
groupIndicator:设置指示符
-->
<ExpandableListView
android:id="@+id/id_elv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:groupIndicator="@drawable/group_indicator"
android:indicatorRight="40dp"
android:indicatorLeft="10dp"/>
</LinearLayout>
group_indicator.xml文件,指定不同状态下的样式
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--展开状态-->
<item android:drawable="@drawable/indicator_expand" android:state_expanded="true">true</item>
<!--非展开状态-->
<item android:drawable="@drawable/indicator_collapse"></item>
</selector>
新建Chapter类和ChapterItem类;Chapter代表分组,ChapterItem代表分组中的子选项;
public class Chapter {
private int id;
private String name;
//存储分组中的的子选项
private List<ChapterItem> chapterItemList = new ArrayList<>();
public Chapter() {
}
public Chapter(int id, String name) {
this.id = id;
this.name = name;
}
//向分组中添加子选项
public void addChapterItem(ChapterItem chapterItem) {
chapterItem.setPid(getId());
chapterItemList.add(chapterItem);
}
//向分组中添加子选项
public void addChapterItem(int cid, String cname) {
ChapterItem chapterItem = new ChapterItem(cid, cname);
chapterItem.setPid(getId());
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ChapterItem> getChapterItemList() {
return chapterItemList;
}
public void setChapterItemList(List<ChapterItem> chapterItemList) {
this.chapterItemList = chapterItemList;
}
}
ChapterItem类
public class ChapterItem {
private String name;
//子选项的id
private int id;
//子选项所在分组的id
private int pid;
public ChapterItem() {
}
public ChapterItem(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
}
ChapterLab类,使用此类模拟添加数据
public class ChapterLab {
public static List<Chapter> getGenerateMockDats() {
List<Chapter> datas = new ArrayList<>();
Chapter root1 = new Chapter(1, "Android");
Chapter root2 = new Chapter(1, "Java");
Chapter root3 = new Chapter(1, "C/C++");
Chapter root4 = new Chapter(1, "Python");
root1.addChapterItem(new ChapterItem(1,"EventBus"));
root1.addChapterItem(new ChapterItem(2, "GreenDao"));
root1.addChapterItem(new ChapterItem(3, "Gridle"));
root1.addChapterItem(new ChapterItem(4, "Spinner"));
root2.addChapterItem(new ChapterItem(5,"spring"));
root2.addChapterItem(new ChapterItem(6, "springmvc"));
root2.addChapterItem(new ChapterItem(7, "mybatis"));
root3.addChapterItem(new ChapterItem(8, "hibernate"));
root3.addChapterItem(new ChapterItem(9,"STL"));
root3.addChapterItem(new ChapterItem(10, "IO"));
root3.addChapterItem(new ChapterItem(11, "指针"));
root3.addChapterItem(new ChapterItem(12, "结构体"));
root4.addChapterItem(new ChapterItem(13,"爬虫"));
root4.addChapterItem(new ChapterItem(14, "数据分析"));
root4.addChapterItem(new ChapterItem(15, "AI"));
root4.addChapterItem(new ChapterItem(16, "人工智能"));
datas.add(root1);
datas.add(root2);
datas.add(root3);
datas.add(root4);
return datas;
}
}
item_parent_chapter.xml文件,父选项布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="#86b2f9">
<TextView
android:id="@+id/id_tv_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="Android"
android:textSize="24dp"
android:textStyle="bold"/>
</LinearLayout>
item_child_layoutu.xml文件,子选项布局文件
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:textSize="16dp"
android:id="@+id/tv_item">
</TextView>
ChapterAdapter数据适配类,这个类继承了BaseExpandableListAdapter并重写了方法,
public class ChapterAdapter extends BaseExpandableListAdapter {
//分组的数据
private List<Chapter> datas;
private LayoutInflater inflater;
private Context mContext;
public ChapterAdapter(Context context, List<Chapter> datas) {
this.datas = datas;
this.mContext = context;
inflater = LayoutInflater.from(context);
}
/**
* 获取分组的个数
* @return
*/
@Override
public int getGroupCount() {
return datas.size();
}
/**
* 获取指定分组中子选项的个数
* @param groupPosition
* @return
*/
@Override
public int getChildrenCount(int groupPosition) {
return datas.get(groupPosition).getChapterItemList().size();
}
/**
* 获取指定分组的数据
* @param groupPosition
* @return
*/
@Override
public Object getGroup(int groupPosition) {
return datas.get(groupPosition);
}
/**
* 获取指定分组中的子选项的数据
* @param groupPosition
* @param childPosition
* @return
*/
@Override
public Object getChild(int groupPosition, int childPosition) {
return datas.get(groupPosition).getChapterItemList().get(childPosition);
}
/**
* 获取指定分组的ID,这个ID必须是唯一的,可以使用分组的position
* @param groupPosition
* @return
*/
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
/**
* 获取子选项的ID,这个ID必须是唯一的,不能使用子条目的position
* @param groupPosition
* @param childPosition
* @return
*/
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
/**
* 分组和子选项是否持有稳定的ID,就是说底层数据的改变会不会影响到它们
* @return
*/
@Override
public boolean hasStableIds() {
return false;
}
/**
* 获取显示指定分组的视图
* @param groupPosition
* @param isExpanded
* @param convertView
* @param parent
* @return
*/
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
ParentViewHolder parentViewHolder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_parent_chapter, parent, false);
parentViewHolder = new ParentViewHolder();
parentViewHolder.tvName = convertView.findViewById(R.id.id_tv_parent);
convertView.setTag(parentViewHolder);
} else {
parentViewHolder = (ParentViewHolder) convertView.getTag();
}
Chapter chapter = datas.get(groupPosition);
parentViewHolder.tvName.setText(chapter.getName());
return convertView;
}
/**
* 获取指定分组中的指定子选项的视图
* @param groupPosition
* @param childPosition
* @param isLastChild
* @param convertView
* @param parent
* @return
*/
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ChildViewHolder childViewHolder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_child_layout, parent, false);
childViewHolder = new ChildViewHolder();
childViewHolder.tvName = convertView.findViewById(R.id.tv_item);
convertView.setTag(childViewHolder);
} else {
childViewHolder = (ChildViewHolder) convertView.getTag();
}
ChapterItem chapterItem = datas.get(groupPosition).getChapterItemList().get(childPosition);
childViewHolder.tvName.setText(chapterItem.getName());
return convertView;
}
/**
* 指定位置上的子元素是否可选中,返回true才会相应点击事件
* @param groupPosition
* @param childPosition
* @return
*/
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public static class ParentViewHolder {
TextView tvName;
}
public static class ChildViewHolder {
TextView tvName;
}
}
主Activity类
public class TestActivity3 extends AppCompatActivity {
private ExpandableListView expandableListView;
private ChapterAdapter chapterAdapter;
private List<Chapter> dataList;
private static final String TAG = "TestActivity3";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test3);
initViews();
initEvents();
}
public void initViews() {
expandableListView = findViewById(R.id.id_elv1);
dataList = ChapterLab.getGenerateMockDats();
chapterAdapter = new ChapterAdapter(this,dataList);
expandableListView.setAdapter(chapterAdapter);
}
public void initEvents() {
//设置子选项被点击监听事件
expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Log.d(TAG, "onChildClick: " + groupPosition + " " + childPosition + " " + id);
return false;
}
});
//设置分组选项被点击监听事件
expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Log.d(TAG, "onGroupClick: " + groupPosition + " " + id);
return false;
}
});
//设置折叠时的监听事件
expandableListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int groupPosition) {
Log.d(TAG, "onGroupCollapse: " + groupPosition);
}
});
//设置展开时的监听事件
expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
Log.d(TAG, "onGroupExpand: " + groupPosition);
}
});
}
}
运行后的效果:
ExpandableListView自带的指示器的效果不好,所以更多情况下我们会选择自定义一个指示器。
修改item_parent_chapter.xml文件,添加一个ImageView控件作为指示符
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="#86b2f9">
<ImageView
android:id="@+id/id_iv_indicator"
android:layout_width="24dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="4dp"
android:background="@drawable/group_indicator"
android:layout_height="24dp"/>
<TextView
android:id="@+id/id_tv_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="Android"
android:textSize="24dp"
android:textStyle="bold"/>
</LinearLayout>
修改主界面布局文件中ExpandableListView的android:groupIndicator属性为@null
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".TestActivity3"
android:orientation="vertical">
<!--
indicatorLeft: 指示符的左边约束距离
indicatorRight:指示符的右边约束距离
groupIndicator:设置指示
-->
<ExpandableListView
android:id="@+id/id_elv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:groupIndicator="@null"
android:indicatorRight="40dp"
android:indicatorLeft="10dp"/>
</LinearLayout>
修改group_indicator.xml文件为
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--当使用ImageView来代替indicator时,使用这个-->
<item android:drawable="@drawable/indicator_expand" android:state_selected="true">true</item>
<!--非展开状态-->
<item android:drawable="@drawable/indicator_collapse"></item>
</selector>
修改ChapterAdapter类中的中的getGroupView方法和ParentViewHolder类为以下所示的样子,
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
ParentViewHolder parentViewHolder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_parent_chapter, parent, false);
parentViewHolder = new ParentViewHolder();
parentViewHolder.tvName = convertView.findViewById(R.id.id_tv_parent);
parentViewHolder.imageView = convertView.findViewById(R.id.id_iv_indicator);
convertView.setTag(parentViewHolder);
} else {
parentViewHolder = (ParentViewHolder) convertView.getTag();
}
Chapter chapter = datas.get(groupPosition);
parentViewHolder.tvName.setText(chapter.getName());
parentViewHolder.imageView.setSelected(isExpanded);
return convertView;
}java
public static class ParentViewHolder {
TextView tvName;
ImageView imageView;
}
运行后效果如图:
标签:return,int,groupPosition,id,学习,ExpandableListView,new,Android,public 来源: https://blog.csdn.net/wsb_2526/article/details/115859654