MCPcopy Index your code
hub / github.com/donkingliang/GroupedRecyclerViewAdapter

github.com/donkingliang/GroupedRecyclerViewAdapter @2.4.3

Chat with this repo
repository ↗ · DeepWiki ↗ · release 2.4.3 ↗ · + Follow
417 symbols 1,006 edges 40 files 136 documented · 33%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

GroupedRecyclerViewAdapter

GroupedRecyclerViewAdapter可以很方便的实现RecyclerView的分组显示,并且每个组都可以包含组头、组尾和子项;可以方便实现多种Type类型的列表,可以实现如QQ联系人的列表一样的列表展开收起功能,还可以实现头部悬浮吸顶功能等。下面先让我们看一下它所能够实现的一些效果:

效果图

分组的列表 不带组尾的列表 不带组头的列表 子项为Grid的列表 子项为Grid的列表(各组子项的Span不同) 头、尾和子项都支持多种类型的列表

多种子项类型的列表

还可以很容易的实时列表的展开收起效果:

可展开收起的列表

还可以轻松实现头部悬浮吸顶的效果:

头部吸顶的列表

以上展示的只是GroupedRecyclerViewAdapter能实现的一些常用效果,其实使用GroupedRecyclerViewAdapter还可以很容易的实现一些更加复杂的列表效果。在我的GroupedRecyclerViewAdapter项目的Demo中给出了上面几种效果的实现例子,并且有详细的注释说明,有兴趣的同学可以到我的GitHub下载源码。下面直接讲解GroupedRecyclerViewAdapter的使用。

引入依赖

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

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

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


// 使用了Androidx

implementation 'com.github.donkingliang:GroupedRecyclerViewAdapter:2.4.1'

// 使用Android support包

implementation 'com.github.donkingliang:GroupedRecyclerViewAdapter:2.4.1-support'

基本使用

1、继承GroupedRecyclerViewAdapter

public class GroupedListAdapter extends GroupedRecyclerViewAdapter {
}

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);

还可是重写GroupedRecyclerViewAdapter方法实现头、尾和子项的多种类型item。效果就像上面的第6张图一样。

    //返回头部的viewType。
    public int getHeaderViewType(int groupPosition);

    //返回尾部的viewType。
    public int getFooterViewType(int groupPosition) ;

    //返回子项的viewType。
    public int getChildViewType(int groupPosition, int childPosition) ;

3、设置点击事件的监听

GroupedRecyclerViewAdapter提供了对列表的点击事件的监听方法。

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

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

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

4、设置空布局

GroupedRecyclerViewAdapter提供设置空布局的功能,如果列表没有数据的情况下可以显示一个空布局。

// 显示空布局。默认不显示
adapter.showEmptyView(true);

框架提供的默认空布局比较简单,可以通过复写getEmptyView自定义空布局

    @Override
    public View getEmptyView(ViewGroup parent) {
    // 返回自定义空布局
        View view = LayoutInflater.from(mContext).inflate(R.layout.adapter_empty_view, parent, false);
        return view;
    }

框架只提供空布局的设置方法,不会管理空布局。所以如果你的空布局有点击事件等其他的业务逻辑,也需要自己在这个方法实现。

5、使用ItemDecoration

从2.4.0版本开始,支持使用ItemDecoration。之前一直没有对GroupedRecyclerViewAdapter提供ItemDecoration的支持,是因为对于分组的列表,每个分组的ItemDecoration和组头、组尾的ItemDecoration都应该是可以单独设置样式的。这对于自定义ItemDecoration的实现比较麻烦,而且难以实现统一的设置和扩展方式。后来我实现了一个自定义ItemDecoration的库:VariedItemDecoration。使用VariedItemDecoration可以实现在一个列表里显示多种不同样式的ItemDecoration,并且可以非常简单的实现自定义ItemDecoration。基于VariedItemDecoration的实现基础,我实现了多样式ItemDecoration的分组管理,使ItemDecoration可以使用于GroupedRecyclerViewAdapter列表。我在库里提供了可直接使用的GroupedLinearItemDecoration/GroupedGridItemDecoration和用于自定义ItemDecoration的基类AbsGroupedLinearItemDecoration/AbsGroupedGridItemDecoration。

下面我以线性列表为例,说明ItemDecoration使用。

// 空白分割线,只需要设置分割线大小,不需要设置样式,divider为空则只添加间隔,不绘制样式
GroupedLinearItemDecoration itemDecoration = new GroupedLinearItemDecoration(adapter,20, null,20,null,20,null);

// 普通分割线,设置分割线大小和头、尾、子项的分割线样式
GroupedLinearItemDecoration itemDecoration = new GroupedLinearItemDecoration(adapter,20, mHeaderDivider,20,mFooterDivider,20,mChildDivider);

// 自定义分割线,可以根据需要设置每个item的分割线大小和样式
CustomLinearItemDecoration itemDecoration = new CustomLinearItemDecoration(this,adapter);

// 添加分割线
recyclerView.addItemDecoration(itemDecoration);

// 自定义分割线
public class CustomLinearItemDecoration extends AbsGroupedLinearItemDecoration {

    private Drawable headerDivider;
    private Drawable footerDivider;
    private Drawable childDivider1;
    private Drawable childDivider2;

    public CustomLinearItemDecoration(Context context,GroupedRecyclerViewAdapter adapter) {
        super(adapter);

        headerDivider = context.getResources().getDrawable(R.drawable.green_divider);
        footerDivider = context.getResources().getDrawable(R.drawable.purple_divider);
        childDivider1 = context.getResources().getDrawable(R.drawable.pink_divider);
        childDivider2 = context.getResources().getDrawable(R.drawable.orange_divider);
    }

    @Override
    public int getChildDividerSize(int groupPosition, int ChildPosition) {
        // 根据position返回分割线的大小
        return 20;
    }

    @Override
    public Drawable getChildDivider(int groupPosition, int ChildPosition) {
        // 根据position返回Drawable 可以为null
        if(groupPosition % 2 == 0){
            return childDivider1;
        } else {
            return childDivider2;
        }
    }

    @Override
    public int getHeaderDividerSize(int groupPosition) {
        // 根据position返回分割线的大小
        return 30;
    }

    @Override
    public Drawable getHeaderDivider(int groupPosition) {
        // 根据position返回Drawable 可以为null
        return headerDivider;
    }

    @Override
    public int getFooterDividerSize(int groupPosition) {
        // 根据position返回分割线的大小
        return 30;
    }

    @Override
    public Drawable getFooterDivider(int groupPosition) {
        // 根据position返回Drawable 可以为null
        return footerDivider;
    }
}

对于网格列表的ItemDecoration,使用也是一样的,大家可以看我demo中的例子。

如果你想在普通的RecyclerView中使用这种多样式的ItemDecoration,请使用VariedItemDecoration

注意事项

1、对方法重写的注意。

如果我们直接继承RecyclerView.Adapter去实现自己的Adapter时,一般会重写Adapter中的以下几个方法:

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

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

public int getItemCount();

public int getItemViewType(int position);

但如果是使用GroupedRecyclerViewAdapter,就一定不能去重写这几个方法,因为在GroupedRecyclerViewAdapter中已经对这几个方法做了实现,而且是对实现列表分组至关重要的,如果子类重写了这几个方法,可能会破坏GroupedRecyclerViewAdapter的功能。 从前面给出的GroupedRecyclerViewAdapter的方法我们可以看到,这些方法其实就是对应RecyclerView.Adapter的这4个方法的,所以我们直接使用GroupedRecyclerViewAdapter提供的方法即可。 RecyclerView.Adapter中的

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

对应GroupedRecyclerViewAdapter中的

    //返回头部的布局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);

这里之所以返回的是布局id而不是ViewHolder ,是因为在GroupedRecyclerViewAdapter项目中已经提供了一个通用的ViewHolder:BaseViewHolder。所以使用者只需要提供布局的id即可,不需要自己去实现ViewHolder。

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(getLayoutId(mTempPosition, viewType), parent, false);
        return new BaseViewHolder(view);
    }

    private int getLayoutId(int position, int viewType) {
        int type = judgeType(position);
        if (type == TYPE_HEADER) {
            return getHeaderLayout(viewType);
        } else if (type == TYPE_FOOTER) {
            return getFooterLayout(viewType);
        } else if (type == TYPE_CHILD) {
            return getChildLayout(viewType);
        }
        return 0;
    }

RecyclerView.Adapter中的

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

对应GroupedRecyclerViewAdapter中的

    //绑定头部布局数据。(如果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);

RecyclerView.Adapter中的

    public int getItemCount();

对应GroupedRecyclerViewAdapter中的

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

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

RecyclerView.Adapter中的

    public int getItemViewType(int position);

对应GroupedRecyclerViewAdapter中的

    //返回头部的viewType。
    public int getHeaderViewType(int groupPosition);

    //返回尾部的viewType。
    public int getFooterViewType(int groupPosition) ;

    //返回子项的viewType。
    public int getChildViewType(int groupPosition, int childPosition) ;

2、对列表操作的注意

RecyclerView.Adapter提供了一系列对列表进行操作的方法。如:

//更新操作
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);

在GroupedRecyclerViewAdapter不建议使用RecyclerView.Adapter的任何对列表的操作方法,因为这些方法都是基于列表的操作,它的position是相对于整个列表而言的,而GroupedRecyclerViewAdapter是分组的列表,它对列表的操作应该是基于组的。同时GroupedRecyclerViewAdapter使用了组结构来维护整个列表的结构,使我们可以对列表进行组的操作,在列表发生变化时GroupedRecyclerViewAdapter需要及时对组结构进行调整,如果使用了RecyclerView.Adapter中的方法对列表进行更新,GroupedRecyclerViewAdapter可能因为无法及时调整组结构而发生异常。所以在使用中应该避免使用这些方法。GroupedRecyclerViewAdapter同样提供了一系列对列表进行操作的方法,我们应该使用GroupedRecyclerViewAdapter所提供的方法。

```java //** 刷新操作 ***//

//通知数据列表刷新。对应 notifyDataSetChanged();
public void notifyDataChanged();

//通知一组数据刷新,包括组头,组尾和子项
public void notifyGroupChanged(int groupPosition);

//通知多组数据刷新,包括组头,组尾和子项
public void notifyGroupRangeChanged(int groupPosition, int count);

// 通知组头刷新
public void notifyHeaderChanged(int groupPosition);

// 通知组尾刷新
public void notifyFooterChanged(int groupPosition);

// 通知一组里的某个子项刷新
public void notifyChildChanged(int groupPosition, int childPosition);

// 通知一组里的多个子项刷新
public void notifyChildRangeChanged(int groupPosition, int childPosition, int count);

// 通知一组里的所有子项刷新
public void notifyChildrenChanged(int groupPosition);

//****** 删除操作 *****//
// 通知所有数据删除
public void notifyDataRemoved();

// 通知一组数据删除,包括组头,组尾和子项
public void notifyGroupRemoved(int groupPosition);

// 通知多组数据删除,包括组头,组尾和子项
public void notifyGroupRangeRemoved(int groupPosition, int count);

// 通知组头删除
public void notifyHeaderRemoved(int groupPosition);

// 通知组尾删除
public void notifyFooterRemoved(int groupPosition);

// 通知一组里的某个子项删除
public void notifyChildRemoved(int groupPosition, int childPosition);

// 通知一组里的多个子项删除
public void notifyChildRangeRemoved(int groupPosition, int childPosition, int count);

// 通知一组里的所有子项删除
public void notifyChildrenRemoved(int groupPosition);

//****** 插入操作 *****//
// 通知一组数据插入
public void notifyGroupInserted(int groupPo

Extension points exported contracts — how you extend this code

OnHeaderClickListener (Interface)
(no doc) [9 implementers]
groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java
OnFooterClickListener (Interface)
(no doc) [6 implementers]
groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java
OnChildClickListener (Interface)
(no doc) [11 implementers]
groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java
IGroupedItemDecoration (Interface)
@Author donkingliang QQ:1043214265 github:https://github.com/donkingliang @Description @Date 2020/7/6 [2 implementers]
groupedadapter/src/main/java/com/donkingliang/groupedadapter/decoration/IGroupedItemDecoration.java
OnStickyChangedListener (Interface)
(no doc)
groupedadapter/src/main/java/com/donkingliang/groupedadapter/widget/StickyHeaderLayout.java

Core symbols most depended-on inside this repo

get
called by 56
groupedadapter/src/main/java/com/donkingliang/groupedadapter/holder/BaseViewHolder.java
countGroupRangeItem
called by 19
groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java
getChildrenCount
called by 15
groupedadapter/src/main/java/com/donkingliang/groupedadapter/structure/GroupStructure.java
getGroupPositionForPosition
called by 14
groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java
setText
called by 12
groupedadapter/src/main/java/com/donkingliang/groupedadapter/holder/BaseViewHolder.java
setOnChildClickListener
called by 11
groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java
judgeType
called by 10
groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java
getGroups
called by 10
app/src/main/java/com/donkingliang/groupedadapterdemo/model/GroupModel.java

Shape

Method 369
Class 40
Interface 8

Languages

Java100%

Modules by API surface

groupedadapter/src/main/java/com/donkingliang/groupedadapter/adapter/GroupedRecyclerViewAdapter.java110 symbols
groupedadapter/src/main/java/com/donkingliang/groupedadapter/widget/StickyHeaderLayout.java30 symbols
app/src/main/java/com/donkingliang/groupedadapterdemo/adapter/VariousAdapter.java15 symbols
app/src/main/java/com/donkingliang/groupedadapterdemo/adapter/ExpandableAdapter.java15 symbols
app/src/main/java/com/donkingliang/groupedadapterdemo/adapter/GroupedListAdapter.java14 symbols
groupedadapter/src/main/java/com/donkingliang/groupedadapter/holder/BaseViewHolder.java13 symbols
groupedadapter/src/main/java/com/donkingliang/groupedadapter/decoration/AbsGroupedLinearItemDecoration.java13 symbols
app/src/main/java/com/donkingliang/groupedadapterdemo/adapter/BindingAdapter.java12 symbols
groupedadapter/src/main/java/com/donkingliang/groupedadapter/decoration/AbsGroupedGridItemDecoration.java11 symbols
groupedadapter/src/main/java/com/donkingliang/groupedadapter/decoration/IGroupedItemDecoration.java10 symbols
groupedadapter/src/main/java/com/donkingliang/groupedadapter/decoration/GroupedGridItemDecoration.java10 symbols
app/src/main/java/com/donkingliang/groupedadapterdemo/entity/ExpandableGroupEntity.java10 symbols

For agents

$ claude mcp add GroupedRecyclerViewAdapter \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page