FormLayoutManager -- 解說(2)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章