一手遮天 Android - view(集合类): ExpandableListView 基础
一手遮天 Android - view(集合类): ExpandableListView 基础
示例如下:
/view/collection/ExpandableListViewDemo1.java
/**
* ExpandableListView - 可展开的 ListView
*
* ExpandableListView 的 Adapter 可以用 BaseExpandableListAdapter(最常用的), SimpleExpandableListAdapter, SimpleCursorTreeAdapter
* 关于 ExpandableListView 的知识点,请参见本程序的 MainActivity 中的代码
*/
package com.webabcd.androiddemo.view.collection;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.webabcd.androiddemo.R;
public class ExpandableListViewDemo1 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_collection_expandablelistviewdemo1);
}
}
/layout/activity_view_collection_expandablelistviewdemo1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
/MainActivity.java
/**
* 通过 ExpandableListView 做本程序的导航
*/
package com.webabcd.androiddemo;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.ExpandableListView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.webabcd.androiddemo.utils.Helper;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ExpandableListView mExpandableListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mExpandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
// 获取导航数据
String jsonString = Helper.getAssetString("site_map.json", this);
Type type = new TypeToken<List<MainNavigationBean>>() { }.getType();
Gson gson = new Gson();
final ArrayList<MainNavigationBean> navigationBeanList = gson.fromJson(jsonString, type);
// 为 ExpandableListView 提供 Adapter
final MainExpandableListAdapter adapter = new MainExpandableListAdapter(navigationBeanList);
mExpandableListView.setAdapter(adapter);
// 父的展开事件监听
adapter.setOnGroupExpandedListener(new OnGroupExpandedListener() {
@Override
public void onGroupExpanded(int groupPosition) {
// 每次展开一个分组后,关闭其他的分组
int groupLength = mExpandableListView.getExpandableListAdapter().getGroupCount();
for (int i = 0; i < groupLength; i++) {
if (i != groupPosition && mExpandableListView.isGroupExpanded(i)) {
mExpandableListView.collapseGroup(i);
}
}
}
});
// 父的点击事件监听
mExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
// 要返回 false
return false;
}
});
// 子的点击事件监听
mExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
String className = "com.webabcd.androiddemo" + navigationBeanList.get(groupPosition).getNodeList().get(childPosition).getUrl();
Intent intent = new Intent();
ComponentName componentName = new ComponentName("com.webabcd.androiddemo", className);
intent.setComponent(componentName);
startActivity(intent);
return true;
}
});
}
}
/MainExpandableListAdapter.java
/**
* 自定义 BaseExpandableListAdapter,用于为本程序首页的 ExpandableListView 提供数据和模板
*/
package com.webabcd.androiddemo;
import android.util.Log;
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 MainExpandableListAdapter extends BaseExpandableListAdapter {
private final String LOG_TAG = "MainAdapter";
private List<MainNavigationBean> mNavigationBeanList;
private OnGroupExpandedListener mOnGroupExpandedListener;
public MainExpandableListAdapter(List<MainNavigationBean> navigationBeanList) {
mNavigationBeanList = navigationBeanList;
}
public void setOnGroupExpandedListener(OnGroupExpandedListener onGroupExpandedListener) {
mOnGroupExpandedListener = onGroupExpandedListener;
}
@Override
public int getGroupCount() {
return mNavigationBeanList.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return mNavigationBeanList.get(groupPosition).getNodeList().size();
}
@Override
public Object getGroup(int groupPosition) {
return mNavigationBeanList.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return mNavigationBeanList.get(groupPosition).getNodeList().get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return groupPosition * 10000 + childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
GroupViewHolder groupViewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_expand_group, parent, false);
groupViewHolder = new GroupViewHolder();
groupViewHolder.textViewTitle = (TextView) convertView.findViewById(R.id.textView1);
convertView.setTag(groupViewHolder);
} else {
groupViewHolder = (GroupViewHolder) convertView.getTag();
}
groupViewHolder.textViewTitle.setText(mNavigationBeanList.get(groupPosition).getTitle());
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ChildViewHolder childViewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_expand_child, parent, false);
childViewHolder = new ChildViewHolder();
childViewHolder.textViewTitle = (TextView) convertView.findViewById(R.id.textView1);
convertView.setTag(childViewHolder);
} else {
childViewHolder = (ChildViewHolder) convertView.getTag();
}
childViewHolder.textViewTitle.setText(mNavigationBeanList.get(groupPosition).getNodeList().get(childPosition).getTitle());
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
@Override
public void onGroupExpanded(int groupPosition) {
Log.d(LOG_TAG, "onGroupExpanded() " + groupPosition);
if (mOnGroupExpandedListener != null) {
mOnGroupExpandedListener.onGroupExpanded(groupPosition);
}
}
@Override
public void onGroupCollapsed(int groupPosition) {
Log.d(LOG_TAG, "onGroupCollapsed() " + groupPosition);
}
private static class GroupViewHolder {
TextView textViewTitle;
}
private static class ChildViewHolder {
TextView textViewTitle;
}
}
/MainNavigationBean.java
/**
* 本程序首页的 ExpandableListView 数据源的实体类
*/
package com.webabcd.androiddemo;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class MainNavigationBean {
@SerializedName("title")
private String mTitle; // 父节点 title
@SerializedName("node")
private List<NodeBean> mNodeList; // 子节点列表
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
this.mTitle = title;
}
public List<NodeBean> getNodeList() {
return mNodeList;
}
public void setNodeList(List<NodeBean> nodeList) {
this.mNodeList = nodeList;
}
// 注:可以安装一个名为 GsonFormat 的插件(安装后可通过快捷键 alt + s 调出),其用于将 json 字符串解析为实体类
public static class NodeBean {
@SerializedName("title")
private String mTitle; // 子节点 title
@SerializedName("url")
private String mUrl; // 子节点 url
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
this.mTitle = title;
}
public String getUrl() {
return mUrl;
}
public void setUrl(String url) {
this.mUrl = url;
}
}
}
/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--
divider - 父分隔线(不需要的话可以设置为 @null)
childDivider - 子分隔线(不需要的话可以设置为 @null)
dividerHeight - 分隔线的高度(包括父和子)
groupIndicator - 组图标(可以分别指定组收缩状态和组展开状态的图标)
-->
<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/orange"
android:childDivider="@color/gray"
android:dividerHeight="2dp"
android:groupIndicator="@drawable/selector_expand_group"/>
</LinearLayout>