万能布局管理器VirtualLayout的详解与使用

原文关于VirtualLayout的介绍:

alibaba/vlayout: Project vlayout is a powerfull LayoutManager extension for RecyclerView, it provides a group of layouts for RecyclerView. Make it able to handle a complicate situation when grid, list and other layouts in the same recyclerview.

翻译:

阿里巴巴/vlayout:项目vlayout是一个针对Reclerview组件的强大的LayoutManager(布局管理器)的扩展,它为Reclerview组件提供了一组的布局。使它能够处理一个复杂的情况,当网格,列表和其他布局在同一个Reclerview组件中时。

现在这个框架发展的很好,逐步扩充为一个功能更加完善的框架:http://tangram.pingguohe.net/

设计初衷

通过向Reclerview组件提供自定义的LayoutManager,VirtualLayout能够优雅地在单个视图上布局具有不同样式的子视图。自定义LayoutManager管理一系列的layoutHelpers,其中每个LayoutManager实现特定位置范围项的特定布局逻辑。顺便说一句,还支持实现定制的layoutHelper并将其提供到框架中。

主要特征

  • 提供默认的通用布局实现,将视图和布局解耦。默认布局实现是:
    • LinearLayoutHelper:提供线性布局作为LinearLayoutManager。
    • GridLayoutHelper:提供网格布局作为GridLayoutManager,但提供更多功能。
    • FixLayoutHelper:将视图固定在屏幕的特定位置,视图不与整个页面滚动。
    • ScrollFixLayoutHelper:将视图固定在屏幕的特定位置,但是视图直到滚动到它的位置才会显示。
    • FloatLayoutHelper:浮动视图,在页面上的浮动视图,用户可以拖放它。
    • ColumnLayoutHelper:像GridLayoutHelper那样执行,但将所有子视图布局在一行中。
    • SingleLayoutHelper:只包含一个子视图。
    • OnePlusNLayoutHelper:一个自定义布局,其中一个子视图位于左侧,其他视图位于右侧,您可能不需要这样做。
    • StickyLayoutHelper:当视图位于屏幕内时,滚动视图,但当视图位于屏幕外时,则在开始或结束位置固定视图。
    • StaggeredGridLayoutHelper:提供类似瀑布的布局作为StaggeredGridLayoutManager。
  • 在默认情况下提供的LayoutHelpers通常可以分为两类。一个是非固定的LayoutHelper,如LinearLayoutHelper、GridLayoutHelper等,这意味着这些LayoutHelper的子级将被放置在父容器的流中,并将随容器滚动而滚动。而另一个是FixLayoutHelper,这意味着这些子容器总是在父容器中固定。

使用

① 添加引用,和其他的库使用一样。详情如下:

对于Gradle:

    implementation 'com.alibaba.android:vlayout:1.0.9'

②初始化布局管理器LayoutManager

final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
//初始化布局管理器
final VirtualLayoutManager layoutManager = new VirtualLayoutManager(this);

recyclerView.setLayoutManager(layoutManager);

③初始化回收池的大小

提供一个合理的回收池大小到您的RecycledView,因为默认值可能不符合您的情况,并导致屏幕滚动时重新创建视图。

RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
recyclerView.setRecycledViewPool(viewPool);
//设置回收复用池大小,(如果一屏内相同类型的 View 个数比较多,需要设置一个合适的大小,防止来回滚动时重新创建View)
viewPool.setMaxRecycledViews(0, 10);

注意:上面的演示代码仅用type=0修改项目的循环池大小,它在适配器中有多个类型,您应该更新每个类型的循环池大小。

④设置适配器,有两种方式,分别通过继承不同的类实现

  • 你可以用DelegateAdapter作为根适配器来组合您自己的适配器。只是让它继承DelegateAdapter.Adapter和复写onCreateLayoutHelper方法,DelegateAdapter是V-Layout专门为管理 LayoutHelper定制的 Adapter。
DelegateAdapter delegateAdapter = new DelegateAdapter(layoutManager,hasConsistItemType);
recyclerView.setAdapter(delegateAdapter);

//设置自适配器集合
delegateAdapter.setAdapters(adapters);

//或者设置单独的适配器
CustomAdapter customAdapter = new CustomAdapter(data, new GridLayoutHelper());
//代理适配器添加子适配器
delegateAdapter.addAdapter(customAdapter);

// call notify change when data changes
adapter.notifyDataSetChanged();

注意:何时hasConsistItemType = true,在不同的子适配器中具有相同类型值的项共享相同的类型,它们的视图将在滚动期间重用。什么时候hasConsistItemType = false,在不同的子适配器中具有相同类型值的项不会在内部共享相同的类型。

  • 另一种设置适配器的方法是扩展VirtualLayoutAdapter并实现它,以便对您的业务代码进行深入的组合。
public class MessageAdapter extends VirtualLayoutAdapter {
   ......
}

MyAdapter msgAdapter = new MessageAdapter(layoutManager);

//创建存放layoutHelper的集合
List helpers = new LinkedList<>();

//创建LayoutHelper对象
GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(4);
gridLayoutHelper.setItemCount(25);
//添加到集合
helpers.add(gridLayoutHelper);

//创建LayoutHelper对象
GridLayoutHelper gridLayoutHelper2 = new GridLayoutHelper(2);
gridLayoutHelper2.setItemCount(25);
//添加到集合
helpers.add(gridLayoutHelper2);

//将LayoutHelper对象集合设置到适配器
msgAdapter.setLayoutHelpers(helpers);

//为RecyclerView设置适配器
recyclerView.setAdapter(myAdapter);

注意:当适配器的数据发生变化时,需要调用setLayoutHelpers()方法

推荐关于:RecyclerView回收和复用机制分析:https://www.jianshu.com/p/467ae8a7ca6e

相关代码说明

1 VirtualLayoutAdapter

* 定义:数据适配器。继承自系统的Adaper
* 作用:创建组件 & 绑定数据到组件
* 额外:定义了两个接口:
    * getLayoutHelper():用于返回某个位置组件对应的一个 LayoutHelper
    * setLayoutHelpers():调用此方法设置整个页面所需要的一系列 LayoutHelper
* 这两方法的具体实现委托给 VirtualLayoutManager 完成

2 VirtualLayoutManager

* 定义:布局管理器。继承自系统的 LinearLayoutManager
* 作用:

    * 在 RecyclerView 加载组件或者滑动时调用 VirtualLayoutManager 的 layoutChunk(),返回当前还有哪些空白区域可摆放组件
    * 管理 LayoutHelper 列表
* 额外:实现了 VirtualLayoutAdapter 的 getLayoutHelper() & setLayoutHelpers()

3 LayoutHelper

* 定义:LayoutHelper 寻找器
* 作用:根据页面状态 寻找对应的 LayoutHelper 并返回给 VirtualLayoutManager
    * VirtualLayoutManager 会持有一个 LayoutHelperFinder
    * 当 layoutChunck() 被调用时会传入一个位置参数,告诉 VirtualLayoutManager 当前要布局第几个组件
* VirtualLayoutManager 通知持有的 LayoutHelperFinder 找到传入参数位置对应的 LayoutHelper(每个 LayoutHelper 都会绑定它负责的布局区域的起始位置和结束位置)

4 LayoutHelperFinder

* 定义:布局协助器
* 作用:负责具体的布局逻辑

5 MarginLayoutHelper

* 定义:继承自 LayoutHelper
* 作用:扩展 LayoutHelper,提供了布局常用的 内边距padding、外边距margin 的计算功能

6 BaseLayoutHelper

    * 定义:MarginLayoutHelper 的第一层具体实现
    * 作用:填充 当前LayoutHelper 在屏幕范围内的具体区域 背景色、背景图等逻辑

7 子LayoutHelper

* 定义:MarginLayoutHelper 的第二层具体实现
* 作用:负责具体的布局逻辑
    * 每种 子LayoutHelper 负责一种布局逻辑
    * 重点实现了 beforeLayout()、doLayout()、afterLayout()
    * 特别是 doLayout():会获取一组件,并对组件进行尺寸计算、界面布局
    * V - Layout 默认实现了10种默认布局:(对应同名的LayoutHelper)
* 特别注意:
    * 每一种 LayoutHelper 负责布局一批组件范围内的组件,不同组件范围内的组件之间,如果类型相同,可以在滑动过程中回收复用。因此回收粒度比较细,且可以跨布局类型复用.
    * 支持扩展外部:即注册新的 LayoutHelper,实现特殊的布局方式。下面会详细说明

你可能感兴趣的:(android)