Android可折叠收缩伸展的Expandable分组RecyclerView:模型抽象和封装(二)
如今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 

更多相关文章

  1. android 显示gif图片
  2. android Thread和Runnable的区别
  3. Android(安卓)ExpandableListView 可展开的ListView
  4. android activity 实现半透明Translucent效果
  5. Android中使用自定义Dialog时match_parent无效的问题
  6. Android(安卓)控件系列: GridView 的简单使用
  7. Android(安卓)不通过parent实现样式继承
  8. 接收短信启动相应服务
  9. Android中动态设置多继承Style/Theme

随机推荐

  1. 特效--------圆角 倒影
  2. 做了一个手机上的直播系统
  3. Android(安卓)点击back键两次退出程序
  4. android sqlite数据库封装 实现crud
  5. android对象池之Message
  6. AIDL跨进程通信的使用
  7. Android/OPhone开发完全讲义
  8. Android(安卓)菜单(OptionMenu)大全 建立
  9. 简单android环境搭建,xp系统
  10. listView透明背