Android可折叠收缩伸展的Expandable分组RecyclerView:模型抽象和封装(二)
16lz
2021-12-04
Android可折叠收缩伸展的Expandable分组RecyclerView:模型抽象和封装(二)
如今Android这种可收缩伸展的Expandable RecyclerView是如此常用,在附录1的基础上,我重新把模型进行了抽象和封装,设计了一套新的架构和简洁的使用方式支持这种功能。重点就是ExpandableItemAdapter类,可直接把RecyclerView的Adapter直接继承ExpandableItemAdapter,然后在建立数据模型时候,把具有“组”意义的数据添加子Item时候,调用addSubItem,这样该RecyclerView就具有伸缩和展开的功能。
每一个Item内部存储了一个isExpand值,isExpand值决定在ExpandableItemAdapter初始后每一组是否伸展和收缩。isExpand为true时候,展开,为false时候,收起。
以下是全部代码。
Item.java:
ItemVH.java:
最重要的是ExpandableItemAdapter,ExpandableItemAdapter实现了全部的展开和折叠Item的功能。ExpandableItemAdapter是可以直接拿来作为RecyclerView的Adapter使用,开发者可以直接继承ExpandableItemAdapter以实现RecyclerView分组的折叠和展开功能。
ExpandableItemAdapter.java:
现给出一个使用例子:
过了三秒,更新了第0组全部数据。
附录:
1,《Android可收缩伸展的Expandable分组RecyclerView》链接:https://blog.csdn.net/zhangphil/article/details/79814332
如今Android这种可收缩伸展的Expandable RecyclerView是如此常用,在附录1的基础上,我重新把模型进行了抽象和封装,设计了一套新的架构和简洁的使用方式支持这种功能。重点就是ExpandableItemAdapter类,可直接把RecyclerView的Adapter直接继承ExpandableItemAdapter,然后在建立数据模型时候,把具有“组”意义的数据添加子Item时候,调用addSubItem,这样该RecyclerView就具有伸缩和展开的功能。
每一个Item内部存储了一个isExpand值,isExpand值决定在ExpandableItemAdapter初始后每一组是否伸展和收缩。isExpand为true时候,展开,为false时候,收起。
以下是全部代码。
Item.java:
package app.zhangphil.exp;import java.util.ArrayList;import java.util.UUID;public abstract class Item { /** * 上层用户可以把此id作为Item的标识。 */ public int id; public int position; public boolean isExpand = true; /** * 当添加子Item时候,需要把当前的uniqueId作为子Item的parentUniqueId记录。 * * 注意:虽然是public属性,但上层用户不应该使用uniqueId和parentUniqueId寻找和比对Item。 * uniqueId和parentUniqueId仅用来处理底层的数据逻辑。 */ public String parentUniqueId = null; public final String uniqueId = UUID.randomUUID().toString(); private ArrayList- items = new ArrayList<>(); public abstract int getType(); /** * 添加该Item的子Item * * @param item */ public void addSubItem(Item item) { item.parentUniqueId = uniqueId; items.add(item); } public void clearSubItems(){ items.clear(); } public ArrayList
- getSubItems() { return items; }}
该Item类是RecyclerView装载的条目的数据抽象模型,开发者的数据对象要继承自该Item,并重写返回类型。addSubItem将(递归)添加二级(子)Item。 ItemVH.java:
package app.zhangphil.exp;import android.support.v7.widget.RecyclerView;import android.view.View;public abstract class ItemVH extends RecyclerView.ViewHolder { public ItemVH(View itemView) { super(itemView); } public abstract int getType();}
ItemVH继承自RecyclerView.ViewHolder,本质是一个ViewHolder。 ItemAdapter.java:
package app.zhangphil.exp;import android.support.v7.widget.RecyclerView;import java.util.ArrayList;public abstract class ItemAdapter extends RecyclerView.Adapter { private ArrayList- mItems; public ItemAdapter() { mItems = new ArrayList<>(); } @Override public int getItemCount() { return mItems.size(); } @Override public int getItemViewType(int position) { return mItems.get(position).getType(); } public Item getItem(int pos) { return mItems.get(pos); } public void addItem(Item item) { mItems.add(item); } public void addAll(ArrayList
- lists) { mItems.addAll(lists); } public ArrayList
- getAllItem() { return mItems; } /** * 清空所有Item。 */ public void clear() { mItems.clear(); } /** * 寻找具有特定type和id的Item。 * * @param type * @param id * @return */ public Item getItem(int type, int id) { Item mItem = null; for (int i = 0; i < mItems.size(); i++) { Item item = mItems.get(i); if (item.getType() == type && item.id == id) { mItem = item; } } return mItem; }}
ItemAdapter继承自RecyclerView.Adapter,做了简单的初始化和抽象。 最重要的是ExpandableItemAdapter,ExpandableItemAdapter实现了全部的展开和折叠Item的功能。ExpandableItemAdapter是可以直接拿来作为RecyclerView的Adapter使用,开发者可以直接继承ExpandableItemAdapter以实现RecyclerView分组的折叠和展开功能。
ExpandableItemAdapter.java:
package app.zhangphil.exp;import android.support.annotation.NonNull;import android.text.TextUtils;import android.view.ViewGroup;import java.util.Iterator;public abstract class ExpandableItemAdapter extends ItemAdapter { @NonNull @Override public abstract ItemVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType); @Override public abstract void onBindViewHolder(@NonNull ItemVH holder, int position); /** * 展开Item * * @param item */ public void expand(Item item) { int pos = -1; for (int i = 0; i < getItemCount(); i++) { Item it = getItem(i); if (TextUtils.equals(it.uniqueId, item.uniqueId)) { pos = i; } } getAllItem().set(pos, item); Iterator- iterator = getAllItem().iterator(); while (iterator.hasNext()) { Item it = iterator.next(); if (TextUtils.equals(it.parentUniqueId, item.uniqueId)) { iterator.remove(); } } if (item.getSubItems().size() > 0) { getAllItem().addAll(pos + 1, item.getSubItems()); } item.isExpand = true; if (mExpandableToggleListener != null) { mExpandableToggleListener.onExpand(item); } } /** * 收起Item * * @param item */ public void collapse(Item item) { Iterator
- iterator = getAllItem().iterator(); while (iterator.hasNext()) { Item it = iterator.next(); if (TextUtils.equals(it.parentUniqueId, item.uniqueId)) { iterator.remove(); } } item.isExpand = false; if (mExpandableToggleListener != null) { mExpandableToggleListener.onCollapse(item); } } /** * 更新Item * * @param item */ public void setItem(Item item) { int pos = -1; for (int i = 0; i < getItemCount(); i++) { Item it = getItem(i); if (TextUtils.equals(it.uniqueId, item.uniqueId)) { pos = i; } } getAllItem().set(pos, item); Iterator
- iterator = getAllItem().iterator(); while (iterator.hasNext()) { Item it = iterator.next(); if (TextUtils.equals(it.parentUniqueId, item.uniqueId)) { iterator.remove(); } } if (item.isExpand) { if (item.getSubItems().size() > 0) { getAllItem().addAll(pos + 1, item.getSubItems()); } } else { } } /** * 添加一个Item,该Item可以是一个普通的Item,也可以是一个包含子Item的item。 * * @param item */ @Override public void addItem(Item item) { super.addItem(item); if (item.isExpand) { for (int i = 0; i < item.getSubItems().size(); i++) { super.addItem(item.getSubItems().get(i)); } } else { } } public interface ExpandableToggleListener { public void onExpand(Item item); public void onCollapse(Item item); } private ExpandableToggleListener mExpandableToggleListener = null; public void setExpandableToggleListener(ExpandableToggleListener listener) { this.mExpandableToggleListener = listener; } public void toggle(Item item) { item.isExpand = !item.isExpand; if (item.isExpand) { expand(item); } else { collapse(item); } }}
现给出一个使用例子:
package app.zhangphil.exp;import android.graphics.Color;import android.os.Handler;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends AppCompatActivity { private final int TYPE_GROUP = 0xfa01; private final int TYPE_CHILD = 0xfa02; private RecyclerViewAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = findViewById(R.id.recycler_view); LinearLayoutManager layoutManage = new LinearLayoutManager(this); layoutManage.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManage); mAdapter = new RecyclerViewAdapter(); recyclerView.setAdapter(mAdapter); String[] groupNames = {"A", "B", "C", "D", "E", "F", "G"}; for (int i = 0; i < groupNames.length; i++) { Group group = new Group(); group.id = i; if (i == 0) group.isExpand = true; else { group.isExpand = false; } group.title = groupNames[i]; int count = (int) (Math.random() * 10) % 5 + 1; for (int j = 0; j < count; j++) { Child child = new Child(); child.position = j; child.group = group; group.addSubItem(child); } mAdapter.addItem(group); } mAdapter.setExpandableToggleListener(new ExpandableItemAdapter.ExpandableToggleListener() { @Override public void onExpand(Item item) { Toast.makeText(getApplicationContext(), ((Group) item).title + " 展开", Toast.LENGTH_SHORT).show(); } @Override public void onCollapse(Item item) { Toast.makeText(getApplicationContext(), ((Group) item).title + " 收起", Toast.LENGTH_SHORT).show(); } }); new Handler().postDelayed(new Runnable() { @Override public void run() { //更新第0组 Group mGroup = (Group) mAdapter.getItem(0); mGroup.clearSubItems(); mGroup.title = "zhangphil"; Child child = new Child(); child.group = mGroup; child.position = 2018; mGroup.addSubItem(child); mAdapter.setItem(mGroup); mAdapter.notifyDataSetChanged(); } }, 3000); } public class RecyclerViewAdapter extends ExpandableItemAdapter { @Override public ItemVH onCreateViewHolder(ViewGroup parent, int viewType) { View view; ItemVH itemVH = null; switch (viewType) { case TYPE_GROUP: view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false); itemVH = new GroupVH(view); break; case TYPE_CHILD: view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_2, parent, false); itemVH = new ChildVH(view); break; } return itemVH; } @Override public void onBindViewHolder(ItemVH holder, int position) { Item item = getItem(position); switch (getItemViewType(position)) { case TYPE_GROUP: final Group g = (Group) item; GroupVH groupVH = (GroupVH) holder; groupVH.text.setText(g.title); groupVH.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { toggle(g); notifyDataSetChanged(); } }); break; case TYPE_CHILD: Child c = (Child) item; ChildVH childVH = (ChildVH) holder; childVH.text1.setText(c.group.title); childVH.text2.setText(c.position + ""); break; } } } private class Group extends Item { public String title; @Override public int getType() { return TYPE_GROUP; } } private class Child extends Item { public Group group; @Override public int getType() { return TYPE_CHILD; } } private class GroupVH extends ItemVH { public TextView text; public GroupVH(View itemView) { super(itemView); text = itemView.findViewById(android.R.id.text1); text.setBackgroundColor(Color.RED); } @Override public int getType() { return TYPE_GROUP; } } private class ChildVH extends ItemVH { public TextView text1; public TextView text2; public ChildVH(View itemView) { super(itemView); text1 = itemView.findViewById(android.R.id.text1); text2 = itemView.findViewById(android.R.id.text2); text1.setTextColor(Color.LTGRAY); text2.setTextColor(Color.BLUE); } @Override public int getType() { return TYPE_CHILD; } }}
初始后,由于第0个Group的isExpand为true,其他Group均为fasle,所以展开第0组,折叠其他组:
过了三秒,更新了第0组全部数据。
伸展或折叠其他组:
项目代码和库已经上传到github上:https://github.com/zhangphil/recyclerview
附录:
1,《Android可收缩伸展的Expandable分组RecyclerView》链接:https://blog.csdn.net/zhangphil/article/details/79814332
更多相关文章
- android 显示gif图片
- android Thread和Runnable的区别
- Android(安卓)ExpandableListView 可展开的ListView
- android activity 实现半透明Translucent效果
- Android中使用自定义Dialog时match_parent无效的问题
- Android(安卓)控件系列: GridView 的简单使用
- Android(安卓)不通过parent实现样式继承
- 接收短信启动相应服务
- Android中动态设置多继承Style/Theme