FormLayoutManager首页,里面有github地址
前言
这篇主要说FormLayoutManager两个处理滑动逻辑的方法,scrollVerticallyBy和scrollHorizontallyBy,说完基本把FormLayoutManager的内容都解析完了。
scrollVerticallyBy
mSumDy的计算逻辑,跟我推荐给大家看的自定义LayoutManager的文章是一样的,这里就不多说。对比那位大神的文章,你可以发现scrollVerticallyBy的代码几乎没太大差别,所以我就不打算说。下面就是总结,谢谢观看!
开玩笑的,有那么一点不同,我就说那些不同点。
//回收越界子View
List<Integer> recylerPostions = new ArrayList<>();
List<View> recylerChilds = new ArrayList<>();
for (int i = getChildCount() - 1; i >= 0; i--) {
View child = getChildAt(i);
int position = getPosition(child);
Rect rect = mItemRects.get(position);
if (!Rect.intersects(rect, visibleRect)) {
// 先要记录要回收的view和position,不能在这里回收,放在后面回收
// 当我们不是手势操作滑动,是调用RecyclerView.scrollBy的方法来滚动大距离是,下面的firstView会变空
recylerPostions.add(position);
recylerChilds.add(child);
}
else {
layoutDecoratedWithMargins(child, rect.left - mSumDx, rect.top - mSumDy, rect.right - mSumDx,
rect.bottom - mSumDy);
mHasAttachedItems.set(position, true);
}
}
首先,对于回收越界的itemview,我是先记录在recylerPosition和recylerChilds,然后放到scrollVerticallyBy代码的末端才进行回收。因为当RecyclerView执行scrollBy的方法滚动,不是用户手动滚动的时候,若scrollBy移动了一段很大的距离,itemview在前面回收掉的话,接下来的getChildAt(0)返回的firstView,是空的,然后会报异常。下面说一下插入view的方法
/**
* 插入行的view
* @param pos
* @param recycler
* @param isSmoothDown 是否为下滑,true:下滑;false:上滑
*/
private void insertRowView(int pos, RecyclerView.Recycler recycler, boolean isSmoothDown) {
Rect visibleRect = getVisibleArea();
Rect rect = mItemRects.get(pos);
if (Rect.intersects(visibleRect, rect) && !mHasAttachedItems.get(pos)) {
View child = recycler.getViewForPosition(pos);
if (isSmoothDown) {
addView(child, 0);
}
else {
addView(child);
}
measureChildWithMargins(child, 0, 0);
layoutDecoratedWithMargins(child, rect.left - mSumDx, rect.top - mSumDy, rect.right - mSumDx,
rect.bottom - mSumDy);
mHasAttachedItems.set(pos, true);
}
}
首页判断该itemView是否在可视区域,并且view还没被回收,这时就符合我们插入view的条件。关键插入的view的位置怎么确认呢?
layoutDecoratedWithMargins(child, rect.left - mSumDx, rect.top - mSumDy, rect.right - mSumDx,
rect.bottom - mSumDy);
在表格没滚动过的时候,该itemView的位置是rect.left, rect.top, rect.right, rect.bottom。我们在垂直滚动(scrollVerticallyBy)和水平滚动(scrollHorizontallyBy)的方法了一直有计算垂直和水平滚动过的总距离,所以上面的变动就是itemView当前的位置了。
scrollHorizontallyBy
和scrollVerticallyBy的原理异曲同工,只是对应的一些变量替换而已。那就不多说,自己对比认真看看,就能理解的,相信自己!