ExpandableListView万能adapter封装轻松实现分组列表及单选效果
2017-10-20 22:36
671 查看
在项目开发中有时候会碰到类似于QQ好友列表的分组列表效果的需求,实现的方式有很多种,可以用ListView、RecyclerView等方式实现,其实系统提供了ExpandableListView可以很轻松的实现;ExpandableListView extends ListView所有在用法上和ListView差不多,都需要设置adapter,但是ExpandableListView的adapter需要extends BaseExpandableListAdapter,需要重写里面的getGroupCount()、getChildrenCount()、getGroup()等方法,每写一个adapter就要去重写这些方法,还是挺麻烦的,同时也造成代码的冗余,所有在这里对ExpandableListView adapter进行了封装。
父条目ViewHolder:
子条目ViewHolder:
adapter:
以上就是对ExpandableListView adapter的封装,在使用的时候去extends DefaultAdapter 去实现布局view的加载和数据填充就可以了,这样就方便了很多;
效果如下:
源码地址:
http://pan.baidu.com/s/1nuM223v
父条目ViewHolder:
public abstract class ParentHolder<T> { private View convertView; public ParentHolder() { convertView = initView(); convertView.setTag(this); } public View getConvertView() { return convertView; } @SuppressWarnings("unchecked") protected <T extends View> T findID(View v, int id) { return (T) v.findViewById(id); } public abstract void refreshView(List<T> list, int position, boolean isExpanded);//初始化页面数据 public abstract View initView();//加载页面ui }
子条目ViewHolder:
public abstract class ChildHolder<T> { private View convertView; public ChildHolder() { convertView = initView(); convertView.setTag(this); } public View getConvertView() { return convertView; } @SuppressWarnings("unchecked") protected <T extends View> T findID(View v, int id) { return (T) v.findViewById(id); } public abstract void refreshView(List<T> list, int position);//初始化页面数据 public abstract View initView();//加载页面ui }
adapter:
public abstract class DefaultAdapter<T> extends BaseExpandableListAdapter { private Context mContext; private List<T> parentLists; private Map<T, List<T>> mMap; public DefaultAdapter(Context context, List<T> parentList, Map<T, List<T>> map) { this.mContext = context; this.parentLists = new ArrayList<>(); if (parentLists != null) { this.parentLists.addAll(parentList); } this.mMap = new HashMap<>(); if (mMap != null) { this.mMap.putAll(map); } } /** * 刷新Group数据 * * @param list */ public void nodfiyParentData(List<T> list) { if (list != null) { this.parentLists.clear(); this.parentLists.addAll(list); } notifyDataSetChanged(); } /** * 刷新map数据 * * @param map */ public void nodfiyMapData(Map<T, List<T>> map) { if (map != null) { this.mMap.clear(); this.mMap.putAll(map); } notifyDataSetChanged(); } /** * 父条目的数量 * * @return */ @Override public int getGroupCount() { return parentLists.size(); } /** * 每个父条目对应的子条目的数量 * * @param groupPosition * @return */ @Override public int getChildrenCount(int groupPosition) { T t = parentLists.get(groupPosition); List<T> ts = mMap.get(t); if (ts == null) { ts = new ArrayList<>(); } return ts.size(); } /** * 根据父条目的位置获取对应的对象 * * @param groupPosition * @return */ @Override public Object getGroup(int groupPosition) { return parentLists.get(groupPosition); } /** * 根据子条目的位置获取对应的对象 * * @param groupPosition * @param childPosition * @return */ @Override public Object getChild(int groupPosition, int childPosition) { T t = parentLists.get(groupPosition); List<T> ts = mMap.get(t); if (ts == null) { ts = new ArrayList<>(); } return ts.get(childPosition); } /** * 父位置 * * @param groupPosition * @return */ @Override public long getGroupId(int groupPosition) { return groupPosition; } /** * 子位置 * * @param groupPosition * @param childPosition * @return */ @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return true; } /** * 父布局 * * @param groupPosition * @param isExpanded * @param convertView * @param parent * @return */ @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { ParentHolder<T> holder = null; if (convertView == null) { holder = getParentHolder(); } else { holder = (ParentHolder<T>) convertView.getTag(); } //isExpanded group是否有展开 if (groupPosition < parentLists.size()) { holder.refreshView(parentLists, groupPosition, isExpanded); } return holder.getConvertView(); } protected abstract ParentHolder<T> getParentHolder(); /** * 子布局 * * @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) { ChildHolder<T> holder = null; if (convertView == null) { holder = getChildHolder(); } else { holder = (ChildHolder<T>) convertView.getTag(); } T t = parentLists.get(groupPosition); List<T> ts = mMap.get(t); holder.refreshView(ts, childPosition); return holder.getConvertView(); } protected abstract ChildHolder<T> getChildHolder(); @Override public boolean isChildSelectable(int groupPosition, int childPosition) { //返回true才会触发setOnChildClickListener子条目事件 return true; } }
以上就是对ExpandableListView adapter的封装,在使用的时候去extends DefaultAdapter 去实现布局view的加载和数据填充就可以了,这样就方便了很多;
public class ExpandableActivity extends AppCompatActivity { private ExpandableListView expandedList; private List<DataInfo> pList = new ArrayList<>(); private Map<DataInfo, List<DataInfo>> cMap = new HashMap<>(); private ExpandableAdapter adapter; private int groupItemSelect = -1; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_expandable); setData(); expandedList = (ExpandableListView) findViewById(R.id.expanded_list); adapter = new ExpandableAdapter(this, pList, cMap); //设置adapter expandedList.setAdapter(adapter); //子条目点击事件 expandedList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { if (groupItemSelect == -1 || groupItemSelect == groupPosition) { setChildSelect(groupPosition, childPosition); } else { setChildSelect(groupPosition, childPosition); DataInfo dataInfo2 = pList.get(groupItemSelect); List<DataInfo> dataInfos1 = cMap.get(dataInfo2); for (DataInfo info : dataInfos1) { info.childItemSelect = false; } cMap.put(dataInfo2, dataInfos1); } Toast.makeText(ExpandableActivity.this, "groupPosition-->" + groupPosition + "childPosition-->" + childPosition, Toast.LENGTH_LONG).show(); adapter.nodfiyMapData(cMap); groupItemSelect = groupPosition; return false; } }); //Group点击事件 expandedList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { DataInfo dataInfo = pList.get(groupPosition); Toast.makeText(ExpandableActivity.this, dataInfo.itemTitle, Toast.LENGTH_LONG).show(); return false; } }); //设置group左边图标 设置为null代表将其隐藏掉 expandedList.setGroupIndicator(null); spreadListView(); } private void setChildSelect(int group, int child) { DataInfo dataInfo = pList.get(group); List<DataInfo> dataInfos = cMap.get(dataInfo); DataInfo dataInfo1 = dataInfos.get(child); String childItemId = dataInfo1.childItemId; for (DataInfo info : dataInfos) { String itemId = info.childItemId; if (childItemId.equals(itemId)) { info.childItemSelect = true; } else { info.childItemSelect = false; } } cMap.put(dataInfo, dataInfos); } /** * 默认展开第一组 要在setAdapter后调用 */ private void spreadListView() { int groupCount = adapter.getGroupCount(); if (groupCount > 0) { expandedList.expandGroup(0); } } /** * 数据适配器 */ class ExpandableAdapter extends DefaultAdapter<DataInfo> { public ExpandableAdapter(Context context, List<DataInfo> parentList, Map<DataInfo, List<DataInfo>> map) { super(context, parentList, map); } @Override protected ParentHolder<DataInfo> getParentHolder() { return new PHolder(); } @Override protected ChildHolder<DataInfo> getChildHolder() { return new CHolder(); } } /** * group holder */ class PHolder extends ParentHolder<DataInfo> { TextView tvGroup; ImageView ivIcon; @Override public void refreshView(List<DataInfo> list, int position, boolean isExpanded) { DataInfo dataInfo = list.get(position); tvGroup.setText(dataInfo.itemTitle); //判断group是否有展开 if (isExpanded) { ivIcon.setImageResource(R.drawable.up); } else { ivIcon.setImageResource(R.drawable.down); } } @Override public View initView() { View view = LayoutInflater.from(ExpandableActivity.this).inflate(R.layout.expandable_group, null, false); tvGroup = findID(view, R.id.tv_group); ivIcon = findID(view, R.id.iv_icon); return view; } } /** * child holder */ class CHolder extends ChildHolder<DataInfo> { TextView tvChild; ImageView ivCheck; @Override public void refreshView(List<DataInfo> list, int position) { DataInfo dataInfo = list.get(position); tvChild.setText(dataInfo.itemTitle); boolean childItemSelect = dataInfo.childItemSelect; if (childItemSelect) { ivCheck.setImageResource(R.drawable.check); } else { ivCheck.setImageResource(R.drawable.uncheck); } } @Override public View initView() { View view = LayoutInflater.from(ExpandableActivity.this).inflate(R.layout.expandable_child, null, false); tvChild = findID(view, R.id.tv_child); ivCheck = findID(view, R.id.iv_check); return view; } } private void setData() { for (int i = 0; i < 5; i++) { DataInfo info = new DataInfo(); info.itemTitle = "group" + i; pList.add(info); } for (DataInfo dataInfo : pList) { List<DataInfo> chList = new ArrayList<>(); for (int i = 0; i < 10; i++) { DataInfo info = new DataInfo(); info.itemTitle = "child" + i; info.childItemId = dataInfo.itemTitle + "child" + i; info.childItemSelect = false; chList.add(info); } cMap.put(dataInfo, chList); } }
效果如下:
源码地址:
http://pan.baidu.com/s/1nuM223v
相关文章推荐
- 【深入篇】自定义ExpandableListView,实现二级列表效果
- ExpandableListView实例(三)_实现QQ中"未分组"效果和"未分组"不可编辑删除功能
- Android 开源库StickyListHeadersListView来实现ListView列表分组效果
- 使用ExpandableListView和ExpandableListAdapter实现分组列表
- Android 开源库StickyListHeadersListView来实现ListView列表分组效果
- Android学习第五天————ExpandableListView组件通过适配器BaseExpandableListAdapter实现两层列表项
- ExpandableListView三级列表实现(带选择联动效果)
- ListView 中显示自定义单选列表,实现单选效果(左文字,右图片)
- ExpandableListView 和SwipeLayout 实现双层列表 ,childitem 滑动删除效果
- [Android实例] Expandablelistview实现,仿QQ人员列表,自制Shape
- Android采用ListView实现列表数据的显示--Adapter应用
- 自定义ExpandableListView 实现像QQ好友列表一样的功能
- (VIEW控件)Android之实现QQ好友分组(ExpandableListView)
- android listview ExpandableListView实现多选,单选,全选,edittext实现批量输入
- Android之实现QQ好友分组(ExpandableListView)
- Android仿联系人列表分组悬浮列表实现,自己定义PinnedHeaderListView实现
- [安卓] 16、ListView和GridView结合显示单元实现自定义列表显示效果
- Android中ListView列表Item的圆角效果实现
- 【转】实现展开列ExpandableListView的三种方式之SimpleExpandableListAdapter实例
- CheckedTextView实现ListView的单选效果