一眼看懂GroupedRecyclerViewAdapter的使用

本人学习安卓从看完《第一行代码》就开始用小书匠写markdown做学习笔记(后悔没早点知道这个学习方法,不然学第一行代码会更扎实一点,以后当然会补上的哈哈哈)我的想法是先做一次笔记在小书匠,然后在CSDN发布的时候再重新阅读修改一下,以保证自己能真的记住会用,实在不行就要达到自己要用到时可以一眼看懂的效果.这篇是我几个月前总结的,排版格式emm大家将就着看吧…


这是用于将RecycleView分组的
实际运用的时候直接继承GroupedRecyclerViewAdapter、创建好父/子的数据Bean然后根据系统提示引入重写方法,然后不了解的地方看着目录跳转去解决就好

参考博客

大致效果

1. 准备工作

1.1 引入依赖

在Project的build.gradle在添加以下代码

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

在Module的build.gradle在添加以下代码

    compile 'com.github.donkingliang:GroupedRecyclerViewAdapter:1.3.0'

1.2 继承和实现GroupedRecyclerViewAdapter方法

继承了GroupedRecyclerViewAdapter 后需要实现以下默认方法(直接用提示键一键引入就好)以下是介绍各个抽象方法的作用

    //返回组的数量
    public abstract int getGroupCount();

    //返回当前组的子项数量
    public abstract int getChildrenCount(int groupPosition);

    //当前组是否有头部
    public abstract boolean hasHeader(int groupPosition);

    //当前组是否有尾部
    public abstract boolean hasFooter(int groupPosition);

    //返回头部的布局id。(如果hasHeader返回false,这个方法不会执行)
    public abstract int getHeaderLayout(int viewType);

    //返回尾部的布局id。(如果hasFooter返回false,这个方法不会执行)
    public abstract int getFooterLayout(int viewType);

    //返回子项的布局id。
    public abstract int getChildLayout(int viewType);

    //绑定头部布局数据。(如果hasHeader返回false,这个方法不会执行)
    public abstract void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition);

    //绑定尾部布局数据。(如果hasFooter返回false,这个方法不会执行)
    public abstract void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition);

    //绑定子项布局数据。
    public abstract void onBindChildViewHolder(BaseViewHolder holder,
                                               int groupPosition, int childPosition);

2. 关于点击事件的监听

    //设置组头点击事件
    public void setOnHeaderClickListener(OnHeaderClickListener listener) {
        mOnHeaderClickListener = listener;
    }

    //设置组尾点击事件
    public void setOnFooterClickListener(OnFooterClickListener listener) {
        mOnFooterClickListener = listener;
    }

    // 设置子项点击事件
    public void setOnChildClickListener(OnChildClickListener listener) {
        mOnChildClickListener = listener;
    }

3. 头部尾部子项的布局怎么设置?

    //返回头部的布局id。(如果hasHeader返回false,这个方法不会执行)
    @Override
    public int getHeaderLayout(int viewType) {
        return R.layout.head_item;
    }

    //返回尾部的布局id。(如果hasFooter返回false,这个方法不会执行)
    public abstract int getFooterLayout(int viewType);

    //返回子项的布局id。
    public abstract int getChildLayout(int viewType);

4.头部尾部子项的内容怎么设置?

4.1 数据Bean的设置

头部中注意这个ChildItem就好,就相当于父亲带了个孩子

public class ExpandableGroupItem {
    private String header;
    private String footer;
    private boolean isExpand;
    private ArrayList<ChildItem> childItems;

    public ExpandableGroupItem(String header, String footer, boolean isExpand,
                               ArrayList<ChildItem> children) {
        this.header = header;
        this.footer = footer;
        this.isExpand = isExpand;
        this.childItems = children;
    }
}

子项Bean,就是和之前的普通Adapter一样设置每一个item的内容

public class ChildItem {
    private String doWhat;
    private String point;
    private String tab;
    private String belong;
}

4.2 绑定数据

头部

    @Override
    public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
        ExpandableGroupItem groupItem = mGroups.get(groupPosition);
        //因为这个BaseViewHolder是底层实现的,所以直接传view 的id就好
        holder.setText(R.id.header_text, groupItem.getHeader());
        ImageView ivState = holder.get(R.id.iv_state);
    }

子项也差不多注意和头部的关系(分清楚两个pos就可以)

    @Override
    public void onBindChildViewHolder(BaseViewHolder holder, int groupPosition, int childPosition) {
        //一定要注意子项父项的关系
        ChildItem childItem = mGroups.get(groupPosition).getChildItems().get(childPosition);
        holder.setText(R.id.dowhat, childItem.getDoWhat());
        holder.setText(R.id.point, childItem.getPoint());
    }

5.怎么对列表操作(视图更新)?

//更新操作
public final void notifyDataSetChanged();
public final void notifyItemChanged(int position);
public final void notifyItemChanged(int position, Object payload);
public final void notifyItemRangeChanged(int positionStart, int itemCount);
public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload);

//插入操作
public final void notifyItemInserted(int position);
public final void notifyItemRangeInserted(int positionStart, int itemCount);

//删除操作
public final void notifyItemRemoved(int position)
public final void notifyItemRangeRemoved(int positionStart, int itemCount);

还有更详细的操作请看参考博客

6.注意

6.1 不可以随意重写之前的方法

但如果是使用GroupedRecyclerViewAdapter,就一定不能去重写以下这几个方法(因为这些方法GroupedRecycleViewAdapter底层已经实现了,重写可能会破坏原有的功能)

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType);

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position);

public int getItemCount();

public int getItemViewType(int position);

7.在Activity中使用?

关键是折叠效果的实现和布局的选择,这里是用网格布局

        View view = inflater.inflate(R.layout.fragment_gatelist, container, false);
        /**
         * 初始化recycleView
         */
        mRecycleView = view.findViewById(R.id.gateList_recyclerView);
        gatewayAdapter = new GatewayAdapter(getActivity(), deviceManagerItems);
        GroupedGridLayoutManager groupedGridLayoutManager = new GroupedGridLayoutManager(getContext(), 2, gatewayAdapter);
        mRecycleView.setLayoutManager(groupedGridLayoutManager);
        gatewayAdapter.setOnHeaderClickListener(new GroupedRecyclerViewAdapter.OnHeaderClickListener() {
            @Override
            public void onHeaderClick(GroupedRecyclerViewAdapter adapter, BaseViewHolder holder,
                                      int groupPosition) {
                GatewayAdapter gatewayAdapter1 = (GatewayAdapter) adapter;
                //如果是展开状态下点击的,就把他折叠
                if (gatewayAdapter1.isExpand(groupPosition)) {
                    gatewayAdapter1.collapseGroup(groupPosition);
                } else {
                    gatewayAdapter1.expandGroup(groupPosition);
                }
            }
        });
        mRecycleView.setAdapter(gatewayAdapter);

补充

怎么实现长按操作?

其实也和RecycleView差不多的,加上合适的前缀就可以运用自如了

    @Override
    public void onBindChildViewHolder(final BaseViewHolder holder, final int groupPosition, final int childPosition) {
       holder.itemView.findViewById(R.id.gateway_layout).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            
            }
        });
        holder.itemView.findViewById(R.id.gateway_layout).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                
                return true;
            }
        });
    }

关于插入子项

初始化数据后还想在特定的分组插入子项应该怎么做?
我自己想了一个正常思路的方法

  1. 先判断头部是否存在,存在就把这个头部的所有子项list取出来,然后再把新childItem添加到这个childItems中
  2. 头部不存在就直接只添加这个新item到这个本来是空的childItems
  3. 再把数据都给ExpandableGroupItem
  4. 添加这个ExpandableGroupItem到之前的list(相同头部的会自动插入子项,新的头部会被创建)
  5. adapter.notifyDataChanged();刷新一下视图
                /**
                 * 如果是已经存在的话就把原来父项item中的childItems赋值过去最后再给回expandableGroupItem保证插入成功
                 */
                ChildItem newItem = new ChildItem(a, b, c, d);
                int i;
                for (i = 0; i < expandableGroupItems.size(); i++) {
                    if (d.equals(expandableGroupItems.get(i).getHeader())) {
                        childItems = expandableGroupItems.get(i).getChildItems();
                        childItems.add(newItem);
                        break;
                    }
                }
                /**
                 * 如果是新的话就直接添加这个item给childItems,然后再给expandableGroupItem保证生成新的父项和子项
                 */
                if (i == expandableGroupItems.size()) {
                    childItems.add(newItem);
                }
                ExpandableGroupItem expandableGroupItem = new ExpandableGroupItem("头部", "尾部", true, childItems);
				 /**
                 * 添加完后就刷新一次list的数据
                 */
                expandableGroupItems.add(expandableGroupItem);
                adapter.notifyDataChanged();

Adapter完整代码

    private static final String TAG = "GatewayAdapter";
    private List<DeviceManagerItem> deviceManagerItems;
    private Activity mContext;

    public GatewayAdapter(Activity context, List<DeviceManagerItem> deviceManagerItems) {
        super(context);
        mContext = context;
        this.deviceManagerItems = deviceManagerItems;
    }

    @Override
    public int getGroupCount() {
        return deviceManagerItems == null ? 0 : deviceManagerItems.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        //如果当前组收起,就直接返回0,否则才返回子项数。这是实现列表展开和收起的关键。
        if (!isExpand(groupPosition)) {
            return 0;
        }
        List<GatewayBean> children = deviceManagerItems.get(groupPosition).getGatewayBeans();
        return children == null ? 0 : children.size();
    }

    @Override
    public boolean hasHeader(int groupPosition) {
        return true;
    }

    @Override
    public boolean hasFooter(int groupPosition) {
        return false;
    }

    @Override
    public int getHeaderLayout(int viewType) {
        return R.layout.header_item;
    }

    @Override
    public int getFooterLayout(int viewType) {
        return 0;
    }

    @Override
    public int getChildLayout(int viewType) {
        return R.layout.item_show_gateway;
    }

    @Override
    public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
        DeviceManagerItem deviceManagerItem = deviceManagerItems.get(groupPosition);
        holder.setText(R.id.header_address, deviceManagerItem.getHeader());
    }

    @Override
    public void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition) {

    }

    @Override
    public void onBindChildViewHolder(final BaseViewHolder holder, final int groupPosition, final int childPosition) {
        final GatewayBean gatewayBean = deviceManagerItems.get(groupPosition).getGatewayBeans().get(childPosition);
        holder.itemView.findViewById(R.id.gateway_layout).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               
            }
        });
        holder.itemView.findViewById(R.id.gateway_layout).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {

                return true;
            }
        });
    }


    /**
     * 判断当前组是否展开
     *
     * @param groupPosition
     * @return
     */
    public boolean isExpand(int groupPosition) {
        DeviceManagerItem entity = deviceManagerItems.get(groupPosition);
        return entity.isExpand();
    }


    /**
     * 展开一个组
     *
     * @param groupPosition
     */
    public void expandGroup(int groupPosition) {
        expandGroup(groupPosition, false);
    }

    /**
     * 展开一个组
     *
     * @param groupPosition
     * @param animate
     */
    public void expandGroup(int groupPosition, boolean animate) {
        DeviceManagerItem entity = deviceManagerItems.get(groupPosition);
        entity.setExpand(true);
        if (animate) {
            // 通知一组里的所有子项插入
            notifyChildrenInserted(groupPosition);
        } else {
            notifyDataChanged();
        }
    }

    /**
     * 收起一个组
     *
     * @param groupPosition
     */
    public void collapseGroup(int groupPosition) {
        collapseGroup(groupPosition, false);
    }

    /**
     * 收起一个组
     *
     * @param groupPosition
     * @param animate
     */
    public void collapseGroup(int groupPosition, boolean animate) {
        DeviceManagerItem entity = deviceManagerItems.get(groupPosition);
        entity.setExpand(false);
        if (animate) {
            notifyChildrenRemoved(groupPosition);
        } else {
            notifyDataChanged();
        }
    }
}

感谢阅读!如有不合理之处还望指出,谢谢!
侵删

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值