Android ExpandableListView是用于将项目显示为垂直滚动的两级列表的视图。 ListView的基本区别在于,它允许显示的两个级别是可以通过触摸查看及其相应子项轻松扩展和折叠的组。为了显示视图,在Android中使用ExpandableListViewAdapter。在许多应用程序中,需要ExpandableListView工具。例如:
- 在“城市”应用程序(适用于任何城市)中,如果用户想查看工程学院的列表/艺术学院的列表/医学院的列表等,
- 蔬菜列表/水果列表/坚果列表等,用于“ jiomart”类型的应用
- 掀背车清单/横切清单/轿车清单等,适用于“ Uber”类应用
重要方法
Methods |
Description |
---|---|
setChildIndicator(Drawable) |
Current state indicator for each item If the child is the last child for a group, the state state_last will be set |
setGroupIndicator(Drawable) |
To represent the state either expanded or collapsed.state_expanded is the state if the group is expanded, state_collapsed if the state of the group is collapsed, state_empty if there are no groups. |
getGroupView() | Used to get the view for the list group header |
getChildView() | Used to get the view for list child item |
值得注意的接口
Interfaces |
Description |
---|---|
ExpandableListView.OnChildClickListener | When a child in the expanded list is clicked, this is overridden |
ExpandableListView.OnGroupClickListener | When a group header in the expanded list is clicked, this is overridden |
ExpandableListView.OnGroupCollapseListener | When a group is collapsed, this method notifies |
ExpandableListView.OnGroupExpandListener | When a group is expanded, this method notifies |
例子
让我们看看在ExpandableListAdapter中使用蔬菜列表/水果列表/坚果列表在Android中实现SimpleExpandableListAdapter的方法。下面给出了一个示例GIF,以了解我们将在本文中做些什么。注意,我们将使用Java语言实现该项目。
步骤1:创建一个新项目
要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Java作为编程语言。
步骤2:创建dimens.xml文件
转到应用程序> res>值>右键单击>新建>值资源文件,并将文件命名为dimens。在此文件中,此处提供了有关尺寸的信息。以下是dimens.xml文件的代码。
XML
16dp
16dp
XML
XML
XML
Java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ExpandableListDataItems {
public static HashMap> getData() {
HashMap> expandableDetailList = new HashMap>();
// As we are populating List of fruits, vegetables and nuts, using them here
// We can modify them as per our choice.
// And also choice of fruits/vegetables/nuts can be changed
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Guava");
fruits.add("Papaya");
fruits.add("Pineapple");
List vegetables = new ArrayList();
vegetables.add("Tomato");
vegetables.add("Potato");
vegetables.add("Carrot");
vegetables.add("Cabbage");
vegetables.add("Cauliflower");
List nuts = new ArrayList();
nuts.add("Cashews");
nuts.add("Badam");
nuts.add("Pista");
nuts.add("Raisin");
nuts.add("Walnut");
// Fruits are grouped under Fruits Items. Similarly the rest two are under
// Vegetable Items and Nuts Items respecitively.
// i.e. expandableDetailList object is used to map the group header strings to
// their respective children using an ArrayList of Strings.
expandableDetailList.put("Fruits Items", fruits);
expandableDetailList.put("Vegetable Items", vegetables);
expandableDetailList.put("Nuts Items", nuts);
return expandableDetailList;
}
}
Java
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import java.util.HashMap;
import java.util.List;
public class CustomizedExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List expandableTitleList;
private HashMap> expandableDetailList;
// constructor
public CustomizedExpandableListAdapter(Context context, List expandableListTitle,
HashMap> expandableListDetail) {
this.context = context;
this.expandableTitleList = expandableListTitle;
this.expandableDetailList = expandableListDetail;
}
@Override
// Gets the data associated with the given child within the given group.
public Object getChild(int lstPosn, int expanded_ListPosition) {
return this.expandableDetailList.get(this.expandableTitleList.get(lstPosn)).get(expanded_ListPosition);
}
@Override
// Gets the ID for the given child within the given group.
// This ID must be unique across all children within the group. Hence we can pick the child uniquely
public long getChildId(int listPosition, int expanded_ListPosition) {
return expanded_ListPosition;
}
@Override
// Gets a View that displays the data for the given child within the given group.
public View getChildView(int lstPosn, final int expanded_ListPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String expandedListText = (String) getChild(lstPosn, expanded_ListPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_item, null);
}
TextView expandedListTextView = (TextView) convertView.findViewById(R.id.expandedListItem);
expandedListTextView.setText(expandedListText);
return convertView;
}
@Override
// Gets the number of children in a specified group.
public int getChildrenCount(int listPosition) {
return this.expandableDetailList.get(this.expandableTitleList.get(listPosition)).size();
}
@Override
// Gets the data associated with the given group.
public Object getGroup(int listPosition) {
return this.expandableTitleList.get(listPosition);
}
@Override
// Gets the number of groups.
public int getGroupCount() {
return this.expandableTitleList.size();
}
@Override
// Gets the ID for the group at the given position. This group ID must be unique across groups.
public long getGroupId(int listPosition) {
return listPosition;
}
@Override
// Gets a View that displays the given group.
// This View is only for the group--the Views for the group's children
// will be fetched using getChildView()
public View getGroupView(int listPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String listTitle = (String) getGroup(listPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_group, null);
}
TextView listTitleTextView = (TextView) convertView.findViewById(R.id.listTitle);
listTitleTextView.setTypeface(null, Typeface.BOLD);
listTitleTextView.setText(listTitle);
return convertView;
}
@Override
// Indicates whether the child and group IDs are stable across changes to the underlying data.
public boolean hasStableIds() {
return false;
}
@Override
// Whether the child at the specified position is selectable.
public boolean isChildSelectable(int listPosition, int expandedListPosition) {
return true;
}
}
Java
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends AppCompatActivity {
ExpandableListView expandableListViewExample;
ExpandableListAdapter expandableListAdapter;
List expandableTitleList;
HashMap> expandableDetailList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
expandableListViewExample = (ExpandableListView) findViewById(R.id.expandableListViewSample);
expandableDetailList = ExpandableListDataItems.getData();
expandableTitleList = new ArrayList(expandableDetailList.keySet());
expandableListAdapter = new CustomizedExpandableListAdapter(this, expandableTitleList, expandableDetailList);
expandableListViewExample.setAdapter(expandableListAdapter);
// This method is called when the group is expanded
expandableListViewExample.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
Toast.makeText(getApplicationContext(), expandableTitleList.get(groupPosition) + " List Expanded.", Toast.LENGTH_SHORT).show();
}
});
// This method is called when the group is collapsed
expandableListViewExample.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int groupPosition) {
Toast.makeText(getApplicationContext(), expandableTitleList.get(groupPosition) + " List Collapsed.", Toast.LENGTH_SHORT).show();
}
});
// This method is called when the child in any group is clicked
// via a toast method, it is shown to display the selected child item as a sample
// we may need to add further steps according to the requirements
expandableListViewExample.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
Toast.makeText(getApplicationContext(), expandableTitleList.get(groupPosition)
+ " -> "
+ expandableDetailList.get(
expandableTitleList.get(groupPosition)).get(
childPosition), Toast.LENGTH_SHORT
).show();
return false;
}
});
}
}
步骤3:使用XML文件
- 为了设计UI,代码以XML形式存在于res \ layout文件夹下。它们被用在活动文件中,一旦XML文件进入活动范围,就可以访问XML中存在的组件。以下是activity_main.xml文件的代码。在代码内部添加了注释,以更详细地了解代码。
XML格式
- 转到应用程序> res>布局>新建>布局资源文件,并将文件命名为list_group。以下是list_group.xml文件的代码。
XML格式
- 接下来是子项的布局行。这是通过list_item.xml文件完成的。转到应用程序> res>布局>新建>布局资源文件,并将文件命名为list_item 。 以下是list_item.xml文件的代码。
XML格式
- 有了以上XML,UI设计元素就完成了。接下来是一个Java文件,用于填充列表的内容。
步骤4:使用Java文件
- 转到应用程序> Java >包名称>右键单击>新建> Java类,然后将该文件命名为ExpandableListDataItems。以下是ExpandableListDataItems的代码。 Java文件。在代码内部添加了注释,以更详细地了解代码。
Java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ExpandableListDataItems {
public static HashMap> getData() {
HashMap> expandableDetailList = new HashMap>();
// As we are populating List of fruits, vegetables and nuts, using them here
// We can modify them as per our choice.
// And also choice of fruits/vegetables/nuts can be changed
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Guava");
fruits.add("Papaya");
fruits.add("Pineapple");
List vegetables = new ArrayList();
vegetables.add("Tomato");
vegetables.add("Potato");
vegetables.add("Carrot");
vegetables.add("Cabbage");
vegetables.add("Cauliflower");
List nuts = new ArrayList();
nuts.add("Cashews");
nuts.add("Badam");
nuts.add("Pista");
nuts.add("Raisin");
nuts.add("Walnut");
// Fruits are grouped under Fruits Items. Similarly the rest two are under
// Vegetable Items and Nuts Items respecitively.
// i.e. expandableDetailList object is used to map the group header strings to
// their respective children using an ArrayList of Strings.
expandableDetailList.put("Fruits Items", fruits);
expandableDetailList.put("Vegetable Items", vegetables);
expandableDetailList.put("Nuts Items", nuts);
return expandableDetailList;
}
}
- 转到应用程序> Java >包名称>右键单击>新建> Java类,并将文件命名为CustomizedExpandableListAdapter。下面是CustomizedExpandableListAdapter的代码。 Java文件。这个Java类扩展BaseExpandableListAdapter,并且它重写ExpandableListView所需的方法。在代码内部添加了注释,以更详细地了解代码。
Java
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import java.util.HashMap;
import java.util.List;
public class CustomizedExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List expandableTitleList;
private HashMap> expandableDetailList;
// constructor
public CustomizedExpandableListAdapter(Context context, List expandableListTitle,
HashMap> expandableListDetail) {
this.context = context;
this.expandableTitleList = expandableListTitle;
this.expandableDetailList = expandableListDetail;
}
@Override
// Gets the data associated with the given child within the given group.
public Object getChild(int lstPosn, int expanded_ListPosition) {
return this.expandableDetailList.get(this.expandableTitleList.get(lstPosn)).get(expanded_ListPosition);
}
@Override
// Gets the ID for the given child within the given group.
// This ID must be unique across all children within the group. Hence we can pick the child uniquely
public long getChildId(int listPosition, int expanded_ListPosition) {
return expanded_ListPosition;
}
@Override
// Gets a View that displays the data for the given child within the given group.
public View getChildView(int lstPosn, final int expanded_ListPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String expandedListText = (String) getChild(lstPosn, expanded_ListPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_item, null);
}
TextView expandedListTextView = (TextView) convertView.findViewById(R.id.expandedListItem);
expandedListTextView.setText(expandedListText);
return convertView;
}
@Override
// Gets the number of children in a specified group.
public int getChildrenCount(int listPosition) {
return this.expandableDetailList.get(this.expandableTitleList.get(listPosition)).size();
}
@Override
// Gets the data associated with the given group.
public Object getGroup(int listPosition) {
return this.expandableTitleList.get(listPosition);
}
@Override
// Gets the number of groups.
public int getGroupCount() {
return this.expandableTitleList.size();
}
@Override
// Gets the ID for the group at the given position. This group ID must be unique across groups.
public long getGroupId(int listPosition) {
return listPosition;
}
@Override
// Gets a View that displays the given group.
// This View is only for the group--the Views for the group's children
// will be fetched using getChildView()
public View getGroupView(int listPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String listTitle = (String) getGroup(listPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_group, null);
}
TextView listTitleTextView = (TextView) convertView.findViewById(R.id.listTitle);
listTitleTextView.setTypeface(null, Typeface.BOLD);
listTitleTextView.setText(listTitle);
return convertView;
}
@Override
// Indicates whether the child and group IDs are stable across changes to the underlying data.
public boolean hasStableIds() {
return false;
}
@Override
// Whether the child at the specified position is selectable.
public boolean isChildSelectable(int listPosition, int expandedListPosition) {
return true;
}
}
- 下面是MainActivity的代码。 Java文件。在代码内部添加了注释,以更详细地了解代码。
Java
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends AppCompatActivity {
ExpandableListView expandableListViewExample;
ExpandableListAdapter expandableListAdapter;
List expandableTitleList;
HashMap> expandableDetailList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
expandableListViewExample = (ExpandableListView) findViewById(R.id.expandableListViewSample);
expandableDetailList = ExpandableListDataItems.getData();
expandableTitleList = new ArrayList(expandableDetailList.keySet());
expandableListAdapter = new CustomizedExpandableListAdapter(this, expandableTitleList, expandableDetailList);
expandableListViewExample.setAdapter(expandableListAdapter);
// This method is called when the group is expanded
expandableListViewExample.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
Toast.makeText(getApplicationContext(), expandableTitleList.get(groupPosition) + " List Expanded.", Toast.LENGTH_SHORT).show();
}
});
// This method is called when the group is collapsed
expandableListViewExample.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int groupPosition) {
Toast.makeText(getApplicationContext(), expandableTitleList.get(groupPosition) + " List Collapsed.", Toast.LENGTH_SHORT).show();
}
});
// This method is called when the child in any group is clicked
// via a toast method, it is shown to display the selected child item as a sample
// we may need to add further steps according to the requirements
expandableListViewExample.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
Toast.makeText(getApplicationContext(), expandableTitleList.get(groupPosition)
+ " -> "
+ expandableDetailList.get(
expandableTitleList.get(groupPosition)).get(
childPosition), Toast.LENGTH_SHORT
).show();
return false;
}
});
}
}
输出:在模拟器上运行
结论
ExpandableListView是许多应用程序中使用的非常有用的强制性功能。在移动应用程序的大小和可用空间中,为了显示多个项目,应该需要诸如ExpandableListView和ExpandableListAdapter之类的功能,以使视图完全适合。由于可以进行滚动,因此我们可以将信息保留在多个级别上。这些方法支持扩展头,折叠头,完美选择子项,如仿真器输出所示。为简单起见,我们提供了Toast消息。根据要求,我们可以添加更多编码以与其匹配。