android:layout_marginRight=“10dp”
android:background="@color/listview_divider"
android:visibility=“visible” />
自定义Adapter
- 继承BaseExpandableListAdapter并实现以下方法
- getGroupCount(获取组项的个数)
- getChildrenCount(获取子项个数)
- getGroup(获取组对象)
- getChild(获取子对象)
- getGroupId(获取组项id)
- getChildId(获取子项id)
- hasStableIds(组和子元素是否持有稳定的ID)
- getGroupView(获取显示指定组的视图对象)
- getChildView(获取显示指定项的视图对象)
- isChildSelectable(子项是否可选中)
- 传入组项列表(如:List<GroupItem>
)
- 传入子项列表(如:List<List<Category>>
)
适配器代码:
com.devilwwj.androiddevelopcourse.adapters.ExpandableListViewAdapter
package com.devilwwj.androiddevelopcourse.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.devilwwj.androiddevelopcourse.R;
import com.devilwwj.androiddevelopcourse.domain.Category;
import com.devilwwj.androiddevelopcourse.domain.GroupItem;
import java.util.HashMap;
import java.util.List;
/**
- 自定义可展开列表的适配器
*/
public class ExpandableListViewAdapter extends BaseExpandableListAdapter {
private Context mContext;// 上下文
private ExpandableListView expandableListView; // 可展开列表对象
private List groupList; // 组列表
private List<List> childList; // 子项列表
private LayoutInflater inflater;
// 自定义接口回调监听器
private OnGroupExpandListener OnGroupExpandListener;
private OnGroupClickListener onGroupClickListener;
private OnChildItemClickListener onChildClickListener;
private HashMap<Integer, Boolean> maps = new HashMap<Integer, Boolean>();
private boolean expandStateAtPosition = false;
public OnGroupClickListener getOnGroupClickListener() {
return onGroupClickListener;
}
public void setOnGroupClickListener(
OnGroupClickListener onGroupClickListener) {
this.onGroupClickListener = onGroupClickListener;
}
public OnGroupExpandListener getOnGroupExpandListener() {
return OnGroupExpandListener;
}
public void setOnGroupExpandListener(
OnGroupExpandListener onGroupExpandListener) {
OnGroupExpandListener = onGroupExpandListener;
}
public OnChildItemClickListener getOnChildClickListener() {
return onChildClickListener;
}
public void setOnChildClickListener(
OnChildItemClickListener onChildClickListener) {
this.onChildClickListener = onChildClickListener;
}
private int mExpandedGroupPosition;
public int getExpandedGroupPosition() {
return mExpandedGroupPosition;
}
public void setExpandedGroupPosition(int mExpandedGroupPosition) {
this.mExpandedGroupPosition = mExpandedGroupPosition;
}
public ExpandableListViewAdapter(Context context,
ExpandableListView expandableListView, List groupList,
List<List> childList) {
super();
this.mContext = context;
this.expandableListView = expandableListView;
this.groupList = groupList;
this.childList = childList;
inflater = LayoutInflater.from(context);
// 初始化列表展开状态
for (int i = 0; i < groupList.size(); i++) {
maps.put(i, false);
}
}
private int mGroupPosition = 0;
private int mChildPosition = 0;
/**
-
设置子项被选中方法
-
@param groupPosition
-
@param childPosition
*/
public void setItemChecked(int groupPosition, int childPosition) {
if (expandableListView == null) {
return;
}
this.mGroupPosition = groupPosition;
this.mChildPosition = childPosition;
int numberOfGroupThatIsOpened = 0;
for (int i = 0; i < groupPosition; i++) {
if (expandableListView.isGroupExpanded(i)) {
numberOfGroupThatIsOpened += this.getChildrenCount(i);
}
}
int position = numberOfGroupThatIsOpened + groupPosition
- childPosition + 1;
if (!expandableListView.isItemChecked(position)) {
expandableListView.setItemChecked(position, true);
}
}
@Override
public int getGroupCount() {
return groupList.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return childList.get(groupPosition).size();
}
/*
-
获得组项 (non-Javadoc)
-
@see android.widget.ExpandableListAdapter#getGroup(int)
*/
@Override
public GroupItem getGroup(int groupPosition) {
return groupList.get(groupPosition);
}
@Override
public Category 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(final int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
final GroupViewHolder groupViewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.layout_expand_group, parent,
false);
groupViewHolder = new GroupViewHolder(convertView);
convertView.setTag(groupViewHolder);
} else {
groupViewHolder = (GroupViewHolder) convertView.getTag();
}
GroupItem groupItem = groupList.get(groupPosition);
groupViewHolder.itemGroupIcon.setBackgroundResource(groupItem
.getDrawableId());
groupViewHolder.itemGroupText.setText(groupItem.getText());
// 如果该组没有子项,则不显示箭头
if (childList.get(groupPosition).size() == 0) {
groupViewHolder.itemArrow.setVisibility(View.GONE);
groupViewHolder.itemGroupLayout
.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onGroupClickListener.onGroupClick(groupPosition);
}
});
} else {
groupViewHolder.itemArrow.setVisibility(View.VISIBLE);
groupViewHolder.itemGroupLayout
.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
OnGroupExpandListener.onGroupExpand(groupPosition);
}
});
}
groupViewHolder.itemGroupText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onGroupClickListener.onGroupClick(groupPosition);
}
});
groupViewHolder.itemArrow.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
OnGroupExpandListener.onGroupExpand(groupPosition);
}
});
// 判断isExpanded就可以控制按下还是关闭,同时更换图片,这里使用属性动画来控制旋转
if (isExpanded) {
groupViewHolder.itemArrow
.setImageResource(R.drawable.ic_leftnav_up);
// 没有孩子项就不隐藏分割线
if (childList.get(groupPosition).size() > 0) {
groupViewHolder.itemDivider.setVisibility(View.INVISIBLE);
} else {
groupViewHolder.itemDivider.setVisibility(View.VISIBLE);
}
} else {
groupViewHolder.itemArrow
.setImageResource(R.drawable.ic_leftnav_down);
groupViewHolder.itemDivider.setVisibility(View.VISIBLE);
}
return convertView;
}
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final ChildViewHolder childViewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.layout_expand_item,
parent, false);
childViewHolder = new ChildViewHolder(convertView);
convertView.setTag(childViewHolder);
} else {
childViewHolder = (ChildViewHolder) convertView.getTag();
}
String content = childList.get(groupPosition).get(childPosition)
.getTitle();
// 设置内容
childViewHolder.itemChildText.setText(content);
// 设置文本点击事件
childViewHolder.itemChildText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onChildClickListener.onChildItemClick(groupPosition,
childPosition);
}
});
if (childPosition == childList.get(groupPosition).size() - 1) {
childViewHolder.itemDivider.setVisibility(View.VISIBLE);
} else {
childViewHolder.itemDivider.setVisibility(View.GONE);
}
// 设置子项被选中的状态
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
// 设置孩子项可选中
return true;
}
private static class GroupViewHolder {
RelativeLayout itemGroupLayout;
ImageView itemGroupIcon;
TextView itemGroupText;
ImageView itemArrow;
View itemDivider;
public GroupViewHolder(View convertView) {
itemGroupLayout = (RelativeLayout) convertView
.findViewById(R.id.group_layout);
itemGroupIcon = (ImageView) convertView
.findViewById(R.id.iv_group_icon);
itemGroupText = (TextView) convertView
.findViewById(R.id.tv_group_text);
itemArrow = (ImageView) convertView.findViewById(R.id.iv_expand);
itemDivider = (View) convertView
.findViewById(R.id.item_group_devider);
}
}
private static class ChildViewHolder {
TextView itemChildText;
View itemDivider;
public ChildViewHolder(View convertView) {
itemChildText = (TextView) convertView
.findViewById(R.id.tv_item_text);
itemDivider = (View) convertView.findViewById(R.id.item_devider);
}
}
public interface OnGroupExpandListener {
void onGroupExpand(int position);
}
public interface OnGroupClickListener {
void onGroupClick(int position);
}
public interface OnChildItemClickListener {
void onChildItemClick(int groupPosition, int childPosition);
}
public boolean getExpandStateAtPosition(int groupPosition) {
// 获得当前位置的展开状态
expandStateAtPosition = maps.get(groupPosition).booleanValue();
return expandStateAtPosition;
}
public void setExpandStateAtPosition(int groupPosition,
boolean expandStateAtPosition) {
this.expandStateAtPosition = expandStateAtPosition;
maps.put(groupPosition, expandStateAtPosition);
}
}
解析一下上面的代码,我们可以看到ExpandableListView除了一个组项,每个组项下面有若干个子项,我们在使用的时候首先要确定要展示的数据结构,组项有groupPosition来标识位置,然而子项需要根据groupPosition和ChildPosition来标识位置,我们设置数据的时候分别在getGroupView和getChildView方法来设置组视图和子项视图数据,最后返回填充数据的视图对象,一些逻辑控制的代码也是在这两个方法中进行,比如控制组项的展开、组项的点击、子项的点击、子项被选中效果等等,这里笔者是自定义了回调接口来满足业务的需求,Android API也提供的类似的方法,大家可以查看官方文档。
Activity代码
com.devilwwj.androiddevelopcourse.activities.ExpandableListViewTestActivity
package com.devilwwj.androiddevelopcourse.activities;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.ExpandableListView;
import com.devilwwj.androiddevelopcourse.R;
import com.devilwwj.androiddevelopcourse.adapters.ExpandableListViewAdapter;
import com.devilwwj.androiddevelopcourse.domain.Category;
import com.devilwwj.androiddevelopcourse.domain.GroupItem;
import com.devilwwj.androiddevelo
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 开源分享
pcourse.utils.ResourceUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
-
A022-列表容器之ExpandableListView
-
@author devilwwj
*/
public class ExpandableListViewTestActivity extends ActionBarActivity implements ExpandableListViewAdapter.OnGroupClickListener, ExpandableListViewAdapter.OnGroupExpandListener
, ExpandableListViewAdapter.OnChildItemClickListener {
private ExpandableListView expandableListView;
private Context mContext;
private ExpandableListViewAdapter expandAdapter;
private List groupList;
private List<List> childList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_expandablelistview);
mContext = ExpandableListViewTestActivity.this;
expandableListView = (ExpandableListView) this.findViewById(R.id.expandablelistview);
expandableListView.setGroupIndicator(null); // 去掉默认指示器
// 设置展开列表数据
setExpandableListView();
}
private void setExpandableListView() {
try {
// 这里分别模拟组项和子项数据
groupList = new ArrayList();
childList = new ArrayList<List>();
ResourceUtil resourceUtil = new ResourceUtil(this);
// 从本地获取目录
String str = getString(R.string.categories);
JSONObject jsonObject = new JSONObject(str);
JSONObject categoryObj = jsonObject.optJSONObject(“categories”);
// 左边侧边栏
JSONArray jsonArray = categoryObj.optJSONArray(“left”);
for (int i = 0; i < jsonArray.length(); i++) {
JSONArray groupArray = jsonArray.getJSONArray(i);
GroupItem groupItem = new GroupItem();
groupItem.setDrawableId(resourceUtil.getResId(“ic_leftnav_”
- (i + 1), “drawable”));
JSONObject groupObj = groupArray.optJSONObject(0);
groupItem.setGroupId(groupObj.optString(“cat_id”)); // 设置组别的分类id
groupItem.setText(groupObj.optString(“title”));
groupList.add(groupItem);
List categories = new ArrayList();
if (groupArray.length() > 0) { // 如果多于一项分类
for (int index = 1; index < groupArray.length(); index++) {
JSONObject itemObj = groupArray.optJSONObject(index);
Category categorie = new Category();
categorie.setTitle(itemObj.optString(“title”));
categorie.setCat_id(itemObj.optString(“cat_id”));
categories.add(categorie);
}
}
childList.add(categories);
}
// 实例化适配器
expandAdapter = new ExpandableListViewAdapter(this, expandableListView, groupList, childList);
expandableListView.setAdapter(expandAdapter);
// 设置ExpandableListView的相关事件监听
// 子项选中、子项被点击、组项展开、组项被点击
// expandableListView.setOnItemSelectedListener(itemSelectedListener);
expandableListView.setOnChildClickListener(mOnChildClickListener);
// expandableListView.setOnGroupExpandListener(mOnGroupExpandListener);
// expandableListView.setOnGroupClickListener(mOnGroupClickListener);