Android ExpandableListView用法示例詳解
引言
在 Android 開發(fā)中,列表展示是一種非常常見的交互形式。而 ExpandableListView 作為一種特殊的列表控件,它允許我們創(chuàng)建具有分組功能的列表,每個分組下還可以包含多個子項,并且分組可以展開和收縮,這大大增強(qiáng)了數(shù)據(jù)展示的靈活性和可讀性。本文將詳細(xì)介紹 ExpandableListView 的用法,從基本概念到具體實現(xiàn),再到高級應(yīng)用,幫助你全面掌握這一控件。
1. ExpandableListView 基本概念
ExpandableListView 繼承自 ListView,是 Android 提供的一種可展開的列表視圖。它主要由分組(Group)和子項(Child)兩部分組成。每個分組可以包含多個子項,用戶可以通過點擊分組來展開或收縮其對應(yīng)的子項列表。這種控件適用于需要對數(shù)據(jù)進(jìn)行分類展示的場景,例如聯(lián)系人列表按照字母分組、商品列表按照類別分組等。
2. 布局文件中添加 ExpandableListView
首先,我們需要在布局文件中添加 ExpandableListView 控件。以下是一個簡單的示例:
<!-- activity_main.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ExpandableListView android:id="@+id/expandableListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
在這個布局中,我們創(chuàng)建了一個垂直的線性布局,并在其中添加了一個 ExpandableListView,其寬度和高度都設(shè)置為 match_parent,以填充整個父布局。
3. 創(chuàng)建數(shù)據(jù)模型
為了展示分組和子項的數(shù)據(jù),我們需要創(chuàng)建相應(yīng)的數(shù)據(jù)模型類。假設(shè)我們要展示一個水果分類列表,每個分類下有不同的水果,我們可以創(chuàng)建如下的數(shù)據(jù)模型類:
// GroupModel.java public class GroupModel { private String groupName; public GroupModel(String groupName) { this.groupName = groupName; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } } // ChildModel.java public class ChildModel { private String childName; public ChildModel(String childName) { this.childName = childName; } public String getChildName() { return childName; } public void setChildName(String childName) { this.childName = childName; } }
GroupModel 類用于表示分組信息,包含一個分組名稱;ChildModel 類用于表示子項信息,包含一個子項名稱。
4. 創(chuàng)建適配器
ExpandableListView 需要使用適配器來將數(shù)據(jù)綁定到視圖上。我們可以繼承 BaseExpandableListAdapter 類來創(chuàng)建自定義適配器。以下是一個示例:
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.TextView; import java.util.List; public class MyExpandableListAdapter extends BaseExpandableListAdapter { private Context context; private List<GroupModel> groupList; private List<List<ChildModel>> childList; public MyExpandableListAdapter(Context context, List<GroupModel> groupList, List<List<ChildModel>> childList) { this.context = context; this.groupList = groupList; this.childList = childList; } @Override public int getGroupCount() { return groupList.size(); } @Override public int getChildrenCount(int groupPosition) { return childList.get(groupPosition).size(); } @Override public Object getGroup(int groupPosition) { return groupList.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return childList.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) { GroupModel groupModel = (GroupModel) getGroup(groupPosition); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(android.R.layout.simple_expandable_list_item_1, null); } TextView groupTextView = convertView.findViewById(android.R.id.text1); groupTextView.setText(groupModel.getGroupName()); return convertView; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { ChildModel childModel = (ChildModel) getChild(groupPosition, childPosition); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(android.R.layout.simple_list_item_1, null); } TextView childTextView = convertView.findViewById(android.R.id.text1); childTextView.setText(childModel.getChildName()); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } }
在這個適配器中,我們需要實現(xiàn)一系列的方法:
- getGroupCount():返回分組的數(shù)量。
- getChildrenCount(int groupPosition):返回指定分組下子項的數(shù)量。
- getGroup(int groupPosition):返回指定位置的分組對象。
- getChild(int groupPosition, int childPosition):返回指定分組下指定位置的子項對象。
- getGroupId(int groupPosition) 和 getChildId(int groupPosition, int childPosition):分別返回分組和子項的 ID。
- getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent):創(chuàng)建并返回分組的視圖。
- getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent):創(chuàng)建并返回子項的視圖。
- isChildSelectable(int groupPosition, int childPosition):指定子項是否可以被選中。
5. 在 Activity 中使用 ExpandableListView
在 Activity 中,我們需要初始化數(shù)據(jù)、創(chuàng)建適配器并將其設(shè)置給 ExpandableListView。以下是示例代碼:
import android.os.Bundle; import android.widget.ExpandableListView; import androidx.appcompat.app.AppCompatActivity; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private ExpandableListView expandableListView; private MyExpandableListAdapter adapter; private List<GroupModel> groupList; private List<List<ChildModel>> childList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); expandableListView = findViewById(R.id.expandableListView); // 初始化數(shù)據(jù) initData(); // 創(chuàng)建適配器 adapter = new MyExpandableListAdapter(this, groupList, childList); // 設(shè)置適配器 expandableListView.setAdapter(adapter); } private void initData() { groupList = new ArrayList<>(); childList = new ArrayList<>(); // 添加分組數(shù)據(jù) GroupModel group1 = new GroupModel("熱帶水果"); GroupModel group2 = new GroupModel("溫帶水果"); groupList.add(group1); groupList.add(group2); // 為每個分組添加子項數(shù)據(jù) List<ChildModel> childList1 = new ArrayList<>(); childList1.add(new ChildModel("香蕉")); childList1.add(new ChildModel("芒果")); childList.add(childList1); List<ChildModel> childList2 = new ArrayList<>(); childList2.add(new ChildModel("蘋果")); childList2.add(new ChildModel("梨")); childList.add(childList2); } }
在 onCreate 方法中,我們首先獲取 ExpandableListView 控件的引用,然后調(diào)用 initData 方法初始化數(shù)據(jù),接著創(chuàng)建適配器并將其設(shè)置給 ExpandableListView。
6. 處理分組和子項的點擊事件
我們可以為 ExpandableListView 添加分組和子項的點擊事件監(jiān)聽器,以實現(xiàn)相應(yīng)的交互邏輯。以下是示例代碼:
// 在 onCreate 方法中添加以下代碼 expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { // 處理分組點擊事件 GroupModel groupModel = (GroupModel) adapter.getGroup(groupPosition); String groupName = groupModel.getGroupName(); // 這里可以添加自定義的邏輯,比如彈出提示框顯示分組名稱 return false; } }); expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { // 處理子項點擊事件 ChildModel childModel = (ChildModel) adapter.getChild(groupPosition, childPosition); String childName = childModel.getChildName(); // 這里可以添加自定義的邏輯,比如跳轉(zhuǎn)到詳情頁面 return false; } });
在分組點擊事件監(jiān)聽器中,我們可以獲取點擊的分組對象并進(jìn)行相應(yīng)的處理;在子項點擊事件監(jiān)聽器中,我們可以獲取點擊的子項對象并進(jìn)行相應(yīng)的處理。
7. 高級應(yīng)用:自定義視圖
除了使用系統(tǒng)提供的簡單布局,我們還可以自定義分組和子項的視圖,以實現(xiàn)更豐富的界面效果。以下是一個自定義視圖的示例:
自定義分組布局文件 group_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp"> <ImageView android:id="@+id/group_icon" android:layout_width="24dp" android:layout_height="24dp" android:src="@mipmap/ic_launcher" /> <TextView android:id="@+id/group_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:textSize="18sp" /> </LinearLayout>
自定義子項布局文件 child_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp"> <ImageView android:id="@+id/child_icon" android:layout_width="24dp" android:layout_height="24dp" android:src="@mipmap/ic_launcher" /> <TextView android:id="@+id/child_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:textSize="16sp" /> </LinearLayout>
修改適配器中的 getGroupView 和 getChildView 方法
@Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { GroupModel groupModel = (GroupModel) getGroup(groupPosition); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.group_item, null); } ImageView groupIcon = convertView.findViewById(R.id.group_icon); TextView groupTextView = convertView.findViewById(R.id.group_name); groupTextView.setText(groupModel.getGroupName()); return convertView; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { ChildModel childModel = (ChildModel) getChild(groupPosition, childPosition); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.child_item, null); } ImageView childIcon = convertView.findViewById(R.id.child_icon); TextView childTextView = convertView.findViewById(R.id.child_name); childTextView.setText(childModel.getChildName()); return convertView; }
通過自定義視圖,我們可以在分組和子項中添加更多的控件,如圖片、按鈕等,從而實現(xiàn)更復(fù)雜的界面效果。
8. 總結(jié)
ExpandableListView 是 Android 中一個非常實用的列表控件,它可以幫助我們實現(xiàn)具有分組功能的列表展示。通過本文的介紹,你應(yīng)該已經(jīng)掌握了 ExpandableListView 的基本用法,包括布局文件的添加、數(shù)據(jù)模型的創(chuàng)建、適配器的實現(xiàn)、點擊事件的處理以及自定義視圖的應(yīng)用。在實際開發(fā)中,你可以根據(jù)具體需求對其進(jìn)行進(jìn)一步的擴(kuò)展和優(yōu)化,以滿足不同的業(yè)務(wù)場景。希望本文對你有所幫助,祝你在 Android 開發(fā)中取得更好的成果!
- Android ExpandableListView雙層嵌套實現(xiàn)三級樹形菜單
- Android ExpandableListView實現(xiàn)下拉刷新和加載更多效果
- Android ExpandableListView單選以及多選實現(xiàn)代碼
- Android ScrollView嵌套ExpandableListView顯示不正常的問題的解決辦法
- Android listview ExpandableListView實現(xiàn)多選,單選,全選,edittext實現(xiàn)批量輸入的實例代碼
- Android 關(guān)于ExpandableListView刷新問題的解決方法
- Android 關(guān)于ExpandableListView去掉里頭分割線的方法
- Android UI控件ExpandableListView基本用法詳解
- Android改變ExpandableListView的indicator圖標(biāo)實現(xiàn)方法
- Android中ExpandableListView的用法實例
- Android ExpandableListView展開列表控件使用實例
相關(guān)文章
Android app開發(fā)中的Fragment入門學(xué)習(xí)教程
這篇文章主要介紹了Android app開發(fā)中的Fragment入門學(xué)習(xí)教程,包括Fragment的創(chuàng)建和XML布局文件中的Fragment定義等,需要的朋友可以參考下2016-02-02Android仿微信列表滑動刪除 如何實現(xiàn)滑動列表SwipeListView
這篇文章主要為大家詳細(xì)介紹了Android仿微信列表滑動刪除,如何實現(xiàn)滑動列表SwipeListView,感興趣的小伙伴們可以參考一下2016-08-08Android開發(fā)高級組件之自動完成文本框(AutoCompleteTextView)用法示例【附源碼下載】
這篇文章主要介紹了Android開發(fā)高級組件之自動完成文本框(AutoCompleteTextView)用法,簡單描述了自動完成文本框的功能并結(jié)合實例形式分析了Android實現(xiàn)自動完成文本框功能的具體步驟與相關(guān)操作技巧,并附帶源碼供讀者下載參考,需要的朋友可以參考下2018-01-01使用Broadcast實現(xiàn)Android組件間的通信
這篇文章主要為大家詳細(xì)介紹了使用Broadcast實現(xiàn)Android組件間的通信,感興趣的小伙伴們可以參考一下2016-06-06Android自定義SurfaceView實現(xiàn)畫板功能
這篇文章主要為大家詳細(xì)介紹了Android自定義SurfaceView實現(xiàn)畫板功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-07-07