【Android】掌握自定义LayoutManager(二) 实现流式布局

本文详细介绍了如何在Android中自定义LayoutManager以实现流式布局,包括滑动方向的处理、逆序布局子View的问题,以及填充和位移的逻辑。重点讨论了在滑动过程中如何回收和填充子View,以及如何处理边界情况,确保布局的正确显示。
摘要由CSDN通过智能技术生成

好了,下面开始正经的写它吧,

@Override

public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {

//位移0、没有子View 当然不移动

if (dy == 0 || getChildCount() == 0) {

return 0;

}

int realOffset = dy;//实际滑动的距离, 可能会在边界处被修复

//边界修复代码

if (mVerticalOffset + realOffset < 0) {//上边界

realOffset = -mVerticalOffset;

} else if (realOffset > 0) {//下边界

//利用最后一个子View比较修正

View lastChild = getChildAt(getChildCount() - 1);

if (getPosition(lastChild) == getItemCount() - 1) {

int gap = getHeight() - getPaddingBottom() - getDecoratedBottom(lastChild);

if (gap > 0) {

realOffset = -gap;

} else if (gap == 0) {

realOffset = 0;

} else {

realOffset = Math.min(realOffset, -gap);

}

}

}

realOffset = fill(recycler, state, realOffset);//先填充,再位移。

mVerticalOffset += realOffset;//累加实际滑动距离

offsetChildrenVertical(-realOffset);//滑动

return realOffset;

}

这里用realOffset变量保存实际的位移,也是return 回去的值。大部分情况下它=dy。

在边界处,为了防止越界,做了一些处理,realOffset 可能不等于dy。

别的文章不同的是,我参考了LinearLayoutManager的源码,先考虑滑动位移进行View的回收、填充(fill()函数),然后再真正的位移这些子Item。


fill()的过程中

流程:

一 会先考虑到dy回收界面上不可见的Item。

填充布局子View

三 判断是否将dy都消费掉了,如果消费不掉:例如滑动距离太多,屏幕上的View已经填充完了,仍有空白,那么就要修正dy给realOffset。

注意事项一:考虑滑动的方向

在填充布局子View的时候,还要考虑滑动的方向,即填充的顺序,是从头至尾填充,还是从尾至头部填充。

如果是向底部滑动,那么是顺序填充,显示底端position更大的Item。( dy>0)

如果是向顶部滑动,那么是逆序填充,显示顶端positon更小的Item。(dy<0)

注意事项二:流式布局 逆序布局子View的问题

再啰嗦最后一点,我们想象一下这个逆序填充的过程:

正序过程可以自上而下,自左向右layout 子View,每次layout之前判断当前这一行宽度+子View宽度,是否超过父控件宽度,如果超过了就另起一行。

逆序时,有两种方案:

1 利用Rect保存子View边界

正序排列时,保存每个子View的Rect

逆序时,直接拿出来,layout

2 逆序化

自右向左layout子View,每次layout之前判断当前这一行宽度+子View宽度,是否超过父控件宽度,

如果超过了就另起一行。并且判断最后一个子View距离父控件左边的offset,平移这一行的所有子View,较复杂,采用方案1.

(我个人认为这两个方案都不太好,希望有朋友能提出更好的方案。)

下面上码:

private SparseArray mItemRects;//key 是View的position,保存View的bounds &#

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值