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的原理異曲同工,只是對應的一些變量替換而已。那就不多說,自己對比認真看看,就能理解的,相信自己!