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的原理异曲同工,只是对应的一些变量替换而已。那就不多说,自己对比认真看看,就能理解的,相信自己!

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