All Projects → donkingliang → Groupedrecyclerviewadapter

donkingliang / Groupedrecyclerviewadapter

Licence: apache-2.0
GroupedRecyclerViewAdapter可以很方便的实现RecyclerView的分组显示,并且每个组都可以包含组头、组尾和子项;可以方便实现多种Type类型的列表,可以实现如QQ联系人的列表一样的列表展开收起功能,还可以实现头部悬浮吸顶功能等。

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to Groupedrecyclerviewadapter

Firestorerecycleradaptersample
Sample Android project using FirestoreRecyclerAdapter
Stars: ✭ 43 (-96.3%)
Mutual labels:  recyclerview, recyclerview-adapter
Lastadapter
Don't write a RecyclerView adapter again. Not even a ViewHolder!
Stars: ✭ 777 (-33.19%)
Mutual labels:  recyclerview, recyclerview-adapter
Easyxrecyclerview
主要提供了简单易用强大的RecyclerView库,包括自定义刷新加载效果、极简通用的万能适配器Adapter、万能分割线、多种分组效果、常见状态页面、item动画效果、添加多个header和footer、侧滑、拖拽、Sticky(黏性)效果、多item布局等,各模块之间灵活、解耦、通用、又能相互组合使用。
Stars: ✭ 607 (-47.81%)
Mutual labels:  recyclerview, recyclerview-adapter
Baserecyclerviewadapterhelper
BRVAH:Powerful and flexible RecyclerAdapter
Stars: ✭ 22,524 (+1836.72%)
Mutual labels:  recyclerview, recyclerview-adapter
Candyview
Implement any RecyclerView in just 1 Line. CandyView handles everything for you.
Stars: ✭ 15 (-98.71%)
Mutual labels:  recyclerview, recyclerview-adapter
Autorecycleradapter
Automated configuration RecyclerView.Adapter for Android
Stars: ✭ 67 (-94.24%)
Mutual labels:  recyclerview, recyclerview-adapter
Codeview Android
Display code with syntax highlighting ✨ in native way.
Stars: ✭ 748 (-35.68%)
Mutual labels:  recyclerview, recyclerview-adapter
Klaster
Declare RecyclerView adapters in a functional way, without boilerplate and subclassing. No compromises on flexibility. If it's possible to do something by subclassing, it's possible to do it with this library.
Stars: ✭ 373 (-67.93%)
Mutual labels:  recyclerview, recyclerview-adapter
Recyclerviewtest
RecyclerView 实践学习的demo,其中有基本的列表,表格,瀑布流,进阶的,等等
Stars: ✭ 23 (-98.02%)
Mutual labels:  recyclerview, recyclerview-adapter
Expandablerecyclerview
A very simple example of how the expandable RecyclerView can be implemented
Stars: ✭ 16 (-98.62%)
Mutual labels:  recyclerview, recyclerview-adapter
Recycler Fast Scroll
Provides fast scroll and section idexer for recycler view
Stars: ✭ 445 (-61.74%)
Mutual labels:  recyclerview, recyclerview-adapter
Rendererrecyclerviewadapter
A single adapter with multiple view types for the whole project
Stars: ✭ 1,061 (-8.77%)
Mutual labels:  recyclerview, recyclerview-adapter
Recyclerviewtemplate
One Template which solves all frequently used RecyclerViews Code Snippets
Stars: ✭ 404 (-65.26%)
Mutual labels:  recyclerview, recyclerview-adapter
Recyclerview Concatadapter
Sample to practice RecyclerView ConcatAdapter
Stars: ✭ 47 (-95.96%)
Mutual labels:  recyclerview, recyclerview-adapter
Brvah kotlin
This is kotlin BRVAH Demo
Stars: ✭ 402 (-65.43%)
Mutual labels:  recyclerview, recyclerview-adapter
Zoomrecylerlayout
🎢 Zoom Recycler Layout Manager For Android Kotlin
Stars: ✭ 618 (-46.86%)
Mutual labels:  recyclerview, recyclerview-adapter
Brv
Android上最强大的RecyclerView库
Stars: ✭ 345 (-70.34%)
Mutual labels:  recyclerview, recyclerview-adapter
Multichoicerecyclerview
Multi choice selection applied on recycler view make life easier
Stars: ✭ 361 (-68.96%)
Mutual labels:  recyclerview, recyclerview-adapter
Multiviewadapter
Easily create complex recyclerview adapters in android
Stars: ✭ 801 (-31.13%)
Mutual labels:  recyclerview, recyclerview-adapter
Flagchatadapter
FlagChatAdapter is easy to implement enchanting recycler view adapter. Just extend your adapter with FlagChatAdapter, impliment some methods and voila! You have got the most beautiful looking chat on your phone. Zero boilerplate code, just put your variables in the right direction.
Stars: ✭ 39 (-96.65%)
Mutual labels:  recyclerview, recyclerview-adapter

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.0'

// 使用Android support包

implementation 'com.github.donkingliang:GroupedRecyclerViewAdapter:2.4.0-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所提供的方法。

	 //****** 刷新操作 *****//

    //通知数据列表刷新。对应 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 groupPosition);

    // 通知多组数据插入
    public void notifyGroupRangeInserted(int groupPosition, int count);

    // 通知组头插入
    public void notifyHeaderInserted(int groupPosition);
    
    // 通知组尾插入
    public void notifyFooterInserted(int groupPosition);

    // 通知一个子项到组里插入
    public void notifyChildInserted(int groupPosition, int childPosition);

    // 通知一组里的多个子项插入
    public void notifyChildRangeInserted(int groupPosition, int childPosition, int count);

    // 通知一组里的所有子项插入
    public void notifyChildrenInserted(int groupPosition);

注意: GroupedRecyclerViewAdapter不管理列表数据源,在调用notifyxxxRemoved或者notifyxxxInserted等方法刷新列表前,请相应的刷新数据源。也就是说,对数据的操作应该写在对列表的刷新前。

3、使用GridLayoutManager的注意

如果要使用GridLayoutManager,一定要使用项目中所提供的GroupedGridLayoutManager。因为分组列表如果要使用GridLayoutManager实现网格布局,就要保证组的头部和尾部是要单独占用一行的。否则组的头、尾可能会跟子项混着一起,造成布局混乱。同时GroupedGridLayoutManager提供了对子项的SpanSize的修改方法,使用GroupedGridLayoutManager可以实现更多的复杂列表布局。

	//直接使用GroupedGridLayoutManager实现子项的Grid效果
    GroupedGridLayoutManager gridLayoutManager = new GroupedGridLayoutManager(this, 2, adapter);
   rvList.setLayoutManager(gridLayoutManager);
   

   GroupedGridLayoutManager gridLayoutManager = new GroupedGridLayoutManager(this, 4, adapter){
       //重写这个方法 改变子项的SpanSize。
       //这个跟重写SpanSizeLookup的getSpanSize方法的使用是一样的。
       @Override
       public int getChildSpanSize(int groupPosition, int childPosition) {
            if(groupPosition % 2 == 1){
                 return 2;
            }
            return super.getChildSpanSize(groupPosition, childPosition);
       }
   };
   rvList.setLayoutManager(gridLayoutManager);

4、BaseViewHolder的使用

项目中提供了一个通用的ViewHolder:BaseViewHolder。提供了根据viewId获取View的方法和对View、TextView、ImageView的常用设置方法。

//根据id获取View
TextView  textView = holder.get(R.id.tv_header);

//View、TextView、ImageView的常用设置方法。并且支持方法连缀调用
holder.setText(R.id.tv_header, "内容")
                .setImageResource(R.id.iv_image, 资源id)
                .setBackgroundRes(R.id.view,资源id);

BaseViewHolder是可以通用的,在普通的Adapter中也可以使用,可以省去每次都要创建ViewHolder的麻烦。

5、头部悬浮吸顶功能

应一些朋友的反馈,我在1.2.0版本中新加了列表的头部悬浮吸顶功能。使用起来非常的简单,只需要用框架里提供的StickyHeaderLayout包裹一下你的RecyclerView就可以了。当然,你需要使用GroupedRecyclerViewAdapter才能看到效果。

    <!-- 用StickyHeaderLayout包裹RecyclerView -->
    <com.donkingliang.groupedadapter.widget.StickyHeaderLayout
        android:id="@+id/sticky_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </com.donkingliang.groupedadapter.widget.StickyHeaderLayout>

StickyHeaderLayout提供了一个设置是否显示悬浮吸顶的方法。

	//是否吸顶,默认为true。
	stickyLayout.setSticky(true);

6、使用DataBinding

GroupedRecyclerViewAdapter在1.3.0版本加入了对DataBinding的支持。要想在Adapter中使用DataBinding,只需要在GroupedRecyclerViewAdapter的构造函数的useBinding参数传true即可。

public class BindingAdapter extends GroupedRecyclerViewAdapter {

    public BindingAdapter(Context context) {
    	//只要在这里传true,Adapter就会用DataBinding的方式加载列表的item布局。默认为false。
        super(context, true);
    }
}

然后同过BaseViewHolder的getBinding()就可以获取到item对应的ViewDataBinding对象。

    @Override
    public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
    	//获取ViewDataBinding对象。
        AdapterBindingHeaderBinding binding = holder.getBinding();
    }

    @Override
    public void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition) {
    	//获取ViewDataBinding对象。
        AdapterBindingFooterBinding binding = holder.getBinding();
    }

    @Override
    public void onBindChildViewHolder(BaseViewHolder holder, int groupPosition, int childPosition) {
    	//获取ViewDataBinding对象。
        AdapterBindingChildBinding binding = holder.getBinding();
    }
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].