MultiType-Adapter 优雅的实现RecyclerVIew中的复杂布局

MultiType-Adapter

一款轻量级支持多数据类型的 RecyclerView 适配器; 使用简单,完全解耦;
这么说吧:通讯聊天界面、朋友圈布局、淘宝 UI等复杂页面 优雅快速实现,无论你是一种数据有多种VIew类型,还是多种数据多种类型,还是两者都有,统统帮你快速地、优雅地搞定!
代码传送门

·总览
·特性
  · 基础用法
  · 单数据
  · 多数据-多类型
  · 单类型-多数据
  · 事件
·高级用法
  · 网格布局与线性布局混合编排
  · 瀑布流布局
  · 上拉加载
  · 无数据时过度界面设置
  · 混合布局拖拽实现
  · 悬浮吸顶效果
  · 设置复用数量
·扩展
·Thrank
`一些说明

总览

总体来讲支持以下效果

总览

特性

· 轻盈、整个类库只有9个文件
  · 全面、支持 bean type 之间 一对一 和 一对多 的关系绑定
  · 职责单一、只负责本分工作,专注多类型的列表视图 类型分发,不会影响 view 的内容或行为
  · 内存、没有性能损失,内存友好
  · 可读、代码清晰干净

基础用法

// root build.gradle
repositories {
    jcenter()
    maven { url "https://www.jitpack.io" }
}
// yout project build.gradle
dependencies {
        compile 'com.github.LidongWen:MultiTypeAdapter:0.2.6'
}

单数据

CommonAdapter adapter = new CommonAdapter<ItemClass>(this, ItemClass.class, R.layout.item_one) {
    @Override
    protected void convert(ViewHolder holder, final ItemClass item, int position) {
        holder.setText(R.id.tv_item01, item.name);
    }
};
....
recyclerView.setAdapter(adapter);

示例查看:single example

多数据-多类型

一个数据类型对应一种viewType

创建一个或多个 class 继承MultiItemView,这边做某一种数据类型 对应的 ItemView的创建,与数据装配

public class ItemVIew01 extends MultiItemView<Bean01> {
    @NonNull
    @Override
    public int getLayoutId() {
        return R.layout.item_one;
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Bean01 item, int position) {
        holder.setText(R.id.tv_item01,item.title);
    }
}
public class Item ...

创建一个 适配器MultiTypeAdapter ,注册 beanMultiItemView 将适配器设入RecyclerView;

private MultiTypeAdapter adapter = new MultiTypeAdapter();
adapter.register(Bean01.class, new ItemVIew01());
adapter.register(Bean02.class, new ItemVIew02());
adapter.register(Bean03.class, new ItemVIew03());
...
adapter.setItems(items);
recyclerView.setAdapter(adapter);

示例查看:many2many Example

单数据-多类型

一种数据类型可以有多种ViewType

创建一个或多个 class 继承MultiItemView,其中 他们的数据类型要一致,重写 isForViewType方法

public class ItemVIew04 extends MultiItemView<Bean04> {
        ...
    @Override
    public boolean isForViewType(Bean04 item, int postion) {
        if (Bean04.TYPE_ONE.equals(item.type)) {
            return true;
        }
        return false;
    }
}

public class ItemVIew05 extends MultiItemView<Bean04> {
        ...
    @Override
    public boolean isForViewType(Bean04 item, int postion) {
        if (Bean04.TYPE_TWO.equals(item.type)) {
            return true;
        }
        return false;
    }
}

创建一个入口 class 继承MultiItemView , 构造函数时调用 addChildeItemView方法

public class ItemVIew06 extends MultiItemView<Bean04> {
    public ItemVIew06() {
        super();
        addChildeItemView(new ItemVIew04());
        addChildeItemView(new ItemVIew05());
        addChildeItemView(new ItemVIew07());
    }
}

activity

       adapter = new MultiTypeAdapter();
       adapter.register(Bean04.class, new ItemVIew06());
       ...

示例查看:one-many Example

事件

设置点击事件于长按事件

       adapter.setOnItemClickListener(new OnItemClickListener<ItemClass>() {
            @Override
            public void onItemClick(View view, RecyclerView.ViewHolder holder, ItemClass itemClass, int position) {
            }

            @Override
            public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, ItemClass itemClass, int position) {
                return false;
            }
        });

高级用法

网格布局与线性布局混合编排

根据数据类型设置 view 比重

    adapter.register(String.class, new ItemVIewNormal()); // 一对一
    adapter.register(Bean01.class, new ItemVIew01());
    adapter.register(Bean02.class, new ItemVIew02());
    adapter.register(Bean03.class, new ItemVIew03());
    adapter.register(Bean04.class, new ItemVIew06());   // 一对多

         final GridLayoutManager layoutManager = new GridLayoutManager(this, SPAN_COUNT);
        GridLayoutManager.SpanSizeLookup spanSizeLookup = new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                Object item = items.get(position);
                if (item instanceof Bean01) {
                    return 1;
                }
                if (item instanceof Bean02) {
                    return 2;
                }
                if (item instanceof Bean03) {
                    return SPAN_COUNT;
                }
                if (item instanceof Bean04 ) {
                    return SPAN_COUNT;
                }
                if (item instanceof String) {
                    return SPAN_COUNT;
                }
                return 2;
            }
        };

示例查看:mix Example

瀑布流布局

示例查看:WaterFall Example

上拉加载

效果如下

loading.gif

将我们的 初始化LoadMoreWrapper2,添加上拉UI

    LoadMoreWrapper2 loadMoreWrapper2;
    private MultiTypeAdapter adapter;
    
    loadMoreWrapper2 = new LoadMoreWrapper2(adapter);
    loadMoreWrapper2.setLoadMoreView(LayoutInflater.from(this).inflate(R.layout.default_loading, recyclerView, false));
    recyclerView.setAdapter(loadMoreWrapper2);
    
    loadMoreWrapper2.setOnLoadMoreListener(new LoadMoreWrapper2.OnLoadMoreListener() {
        @Override
        public void onLoadMoreRequested() {
            loadMoreWrapper2.loadingComplete();//加载完毕
        }
    });
    
    // loadMoreWrapper2.setLoadMore(false); 开启或关闭加载功能

示例查看:pull-load Example

无数据时过度界面设置

    EmptyWrapper emptyWrapper;
    private MultiTypeAdapter adapter;
    
    emptyWrapper = new EmptyWrapper(adapter);
    emptyWrapper.setEmptyView(R.layout.layout_empty);
    recyclerView.setAdapter(emptyWrapper);

示例查看:Empty Example

混合布局拖拽实现

混合布局拖拽实现

吸顶效果

快速打造RecyclerView悬浮吸顶效果
一共有四种模式 请具体查看文章

sticky.gif

设置复用数量

业务需要,设置每种view的最大复用数量

public class ItemVIew01 extends MultiItemView<Bean01> {

    public void getMaxRecycleCount(){
        return 5;
    }
}

扩展

SasukeRecyclerView:基于MultiType-Adapter开发的一框下拉刷新上拉加载的库

Thrank

  • 鸿洋: 空白页功能与上拉加载功能 我拿过来稍微做了修改
  • Glide: 图片加载
  • drakeet学习其中的思想

一些说明

大家可能咋一看,会认为我抄袭 drakeet的代码,我虽然有学习过他的代码,其中也让我受益良多,不论是技术点还是架构松耦合方面的知识,但是,这份开源库虽然使用上与之相似,但完全手写,不存在抄袭 drakeet , 而且 是否抄袭 请大家阅读完源码之后再做评论,谢谢。

V 0.2.6  ·增加黏贴布局类型
V 0.2.5  ·GroupWrapper支持放入其他包中
V 0.2.0  ·分组伸展收缩功能
V 0.1.4
 ·悬浮吸顶效果增强:可随意搭配itemVIew为悬浮布局
 ·事件处理优化
V 0.1.3
 ·检测并修复切换悬浮头部状态时发生内存泄漏;

检测内存泄漏-内存占用图

V 0.1.2
 ·支持悬浮头部触摸事件,点击事件,长按事件等
 ·multiTypeAdapter支持restful风格调用
V 0.1.1
 ·MultiItemView 改变,更加简洁、直观
 ·新增 悬浮吸顶头部功能 快速打造Recyclerview悬浮吸顶头部


V 0.1.1
 ·支持头部吸顶功能
V 0.0.1
 ·实现一对一关系功能
 ·实现一对多关系功能
 ·事件监听
 ·支持网格、瀑布流、线性布局
 ·上拉加载功能
 ·数据为空时过渡界面展示功能

代码传送门:戳我!!!

来上一张架构图


multiTypeAdapter

希望我的文章不会误导在观看的你,如果有异议的地方欢迎讨论和指正。
如果能给观看的你带来收获,那就是最好不过了。

人生得意须尽欢, 桃花坞里桃花庵
点个关注呗,对,不信你点试试?

推荐阅读更多精彩内容