最近比较忙,时间也是被碎片化了导致视频一直没有录制,so 距离上一篇recyclerView系列文章已经有挺久的了,小小的抱歉一下,接下里进入我们的主题 自定义LayoutManager。
还记得在RecyclerView(3)- LayoutMagager源码解析,LinearLayoutManager 当中我们了解了调用recyler
类的回收/复用方法来减少view的创建与复用view,知道了layoutManage
按需加载布局view思路原理,总结了recylerView之所以如此高效性能的原因。
我们就要利用前几章的知识来打造一个 自定义LayoutManager
,其中 复用view、按需加载布局、滑动时按需加载view回收view;
效果如下:
可能有同学看到这里嗤之以鼻,这个还需要自定义layoutManager, 完全我自己自定义一个VIew就好了。 何必这么麻烦还要去继承LayoutManager ?
我来解释下原因:
1、本节是前几章知识总结的产物,也就是说本章是前几章知识的课后习题,所以我们要拿LayoutManager搞事情;
2、从性能方面考虑,这里细心的同学可能发现了,每次itemView滑出屏幕外又滑进来 颜色是变了, 间接地说明了最起码回收了view,按需加载布局(只显示一页布局的view);
3、我们要利用recyclerVIew的回收机制 来打造高性能自定义控件。
1、分析布局
1.1、 正常布局
1、我们根据行标分为单双行,双行显示3个元素,单行显示两个两个元素。
2、下标为0的 item ,的顶点位置为 0,0;
3、双行 中item位置确定
表头的位置: 如下图
双行中非表头的item 位置比较好确定; 坐标位置相比于上一个item x轴平移了一个item的宽度
4、单行itemView位置关系
单行的所有item 都是根据上一个itemVIew位置所确定的
1.2、 滑动时布局
1.2.1、 上滑时布局
如上图所示: 当我上滑时 我需要回收 布局①中的内容,添加布局②中的内容,然后整体向上平移
1.2.2、 下滑时布局
如上图所示 当我下滑时,我需要回收 布局②中的内容,添加布局①中的内容,然后整体向下平移
2、回顾知识
结合 LinearLayoutManager 源码解析 提取我们需要用到的重点方法
// 1、入口:onLayoutChildren
// 2、回收所有view: removerRecyclerAllviews
// 回收单个或多个view : removeAndRecycleViewAt(i, recycler);
// 得到view : recycler.getviewForPositon
//
// 3、 允许滑动 canScrollerVertically() return true;
// 4、消耗滑动距离 scrollerVertically( dy ...)
3、主线框架搭建
public class MyLayoutManager extends LayoutManager {
LayoutState layoutState = new LayoutState();
int rowCount = 4; //双行的数量
public MyLayoutManager(int rowCount) {
this.rowCount = rowCount;
}
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
//回收所有的view
// 计算布局需要的各种数据:
// 布局view 回收view
fill()
}
/**
* 填充view 回收view
*
* @param layoutState
* @param recycler
* @param state
* @return 实际消耗的偏移量 / 实际移动的距离
*/
private int fill(LayoutState layoutState, RecyclerView.Recycler recycler, RecyclerView.State state) {
// 回收view
//添加view
// 自上而下填充
// 双行
// 填充 下标为0的view
// 填充 双行 表头view
// 填充 非行头的view
// 单行
.// 填充单行表头
//填充非行头的view
// 自下而上填充
// 双行
// 填充 双行 行尾view
// 填充 非行尾的view
// 单行
.// 填充单行行尾
//填充非行尾的view
//计算消耗的偏移量 返回
return ;
}
@Override
public boolean canScrollVertically() {
return true;
}
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
// 根据偏移量 计算开始布局的坐标点 各种数据
// 布局view 回收view
// 计算实际消耗的偏移量
// 平移children
//返回实际消耗的偏移量
return super.scrollVerticallyBy(dy, recycler, state);
}
/**
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
* space.
*/
static class LayoutState {
//布局的方向
int mItemDirection; // 1: 从上自下方向 -1 : 自下而上 方向
static final int downDirection = 1; //向上滑动,向下填充
static final int upDirection = -1; // 向下滑动,向上填充
// 开始填充的view的原点
Point startPoint = new Point(0, 0);
// 可用高度
int mAvailable;
/**
* Pixel offset where layout should start
*/
int mOffset;
/**
* Current position on the adapter to get the next item.
*/
public int mCurrentPosition;
public void initAndClear() {
startPoint.set(0, 0);
mAvailable = 0;
mOffset = 0;
mCurrentPosition = 0;
mItemDirection = downDirection;
}
}
}
好了 ,伪代码写好了,我们开始干活吧~~~
文章配套视频地址在下方
· RecyclerView(1)- Decoration源码解析
· RecyclerView(2)- 自定义Decoration打造时光轴效果
· RecyclerView(3)- LayoutMagager源码解析,LinearLayoutManager
· RecyclerView(4)- 核心、Recycler复用机制_1
· RecyclerView(4)- 核心、Recycler复用机制_2
· RecyclerView(5)- 自定义LayoutManager(布局、复用)
· RecyclerView(6)- 自定义ItemAnimator
· RecyclerView(7)- ItemTouchHelper
· RecyclerView(8)- MultiTypeAdapter文章、MultiTypeAdapter Github地址
文章视频地址:链接:http://pan.baidu.com/s/1hssvXC4 密码:18v1
代码地址在视频笔记当中
希望我的文章不会误导在观看的你,如果有异议的地方欢迎讨论和指正。
如果能给观看的你带来收获,那就是最好不过了。