Linkage-RecyclerView icon indicating copy to clipboard operation
Linkage-RecyclerView copied to clipboard

向下滑动时,在两个组别切换的时候,假头会闪一下,Demo中也会出现这个现象

Open WanDa1993 opened this issue 4 years ago • 7 comments

研究源码的过程中,测试发现的。不算大问题,算是一个小瑕疵。顺便感谢下作者~

WanDa1993 avatar Jan 21 '21 07:01 WanDa1993

组别:A B C D E 。。。。 向上滑动 从 D -> C 临界切换的时候会闪一下。

WanDa1993 avatar Jan 21 '21 07:01 WanDa1993

                if (mFirstVisiblePosition != firstPosition && firstPosition >= 0) {
                    mFirstVisiblePosition = firstPosition;
                    mTvHeader.setY(0);

                    String currentGroupName = items.get(mFirstVisiblePosition).isHeader
                            ? items.get(mFirstVisiblePosition).header
                            : items.get(mFirstVisiblePosition).info.getGroup();

                    if (TextUtils.isEmpty(mLastGroupName) || !mLastGroupName.equals(currentGroupName)) {
                        mLastGroupName = currentGroupName;
                        groupNameChanged = true;
                        mTvHeader.setText(mLastGroupName);
                    }
                }

应该在临界的时候 先触发这段代码,先设置Header Y 坐标 = 0 ,然后赋值

WanDa1993 avatar Jan 21 '21 07:01 WanDa1993

然后才执行这段逻辑

            if (firstCompletePosition > 0 && (firstCompletePosition) < items.size()
                    && items.get(firstCompletePosition).isHeader) {

                View view = mSecondaryLayoutManager.findViewByPosition(firstCompletePosition);
                if (view != null && view.getTop() <= mTitleHeight) {
                    mTvHeader.setY(view.getTop() - mTitleHeight);
                }
            }

上移Header

才会造成闪一下

WanDa1993 avatar Jan 21 '21 07:01 WanDa1993

问题我找到了解决思路,在重新描述下问题,以及解决思路,供作者参考:

问题产生场景:

已知组别:A、B、C、D、E

已知占位Header:tvHeader

复现步骤:

(1)先滑动到tvHeader与组别B的头部重合,此时tvHeader显示B

(2)慢速向上滑动,只到A组的底部刚刚出现的临界

(3)tvHeader 会迅速更新成A的名称,然后进行tvHeader.y = -titleHeight的操作

(4)此时会发现tvHeader名称变化成A,然后闪烁一下,之后又显示B组别的Title,这个过程比较快。很容易复现出来

WanDa1993 avatar Jan 21 '21 09:01 WanDa1993

解决方案:

研究下源码,造成这个现象是由于如下代码造成的

LinkageRecyclerView#200

                boolean groupNameChanged = false;

                if (mFirstVisiblePosition != firstPosition && firstPosition >= 0) {
                    mFirstVisiblePosition = firstPosition;
                    mTvHeader.setY(0);

                    String currentGroupName = items.get(mFirstVisiblePosition).isHeader
                            ? items.get(mFirstVisiblePosition).header
                            : items.get(mFirstVisiblePosition).info.getGroup();

                    if (TextUtils.isEmpty(mLastGroupName) || !mLastGroupName.equals(currentGroupName)) {
                        mLastGroupName = currentGroupName;
                        groupNameChanged = true;
                        mTvHeader.setText(mLastGroupName);
                    }
                }

上面这段的代码,我理解的含义是只要发生第一个可见的Item变化,此时就会将tvHeader的y坐标设置成0,然后刷新tvHeader的text

造成原因:

其实在第一个可见Item切换时,会存在两种情况

(1)向下滑动 && 第一个可见Item变化

(2)向上滑动 && 第一个可见Item变化

向下滑动:

向下滑动时&&第一个Item变化,因为此时tvHeader和SecondaryRv的标题Item并不重合,所以不需要重置tvHeader的Y轴坐标,闪烁的本质也是因为重置Y坐标,同时更新Text

向上滑动:

向上滑动时&&第一个Item变化,需要重置tvHeader的Y轴坐标,因为此时tvHeader和SecondaryRv的标题Item重合

WanDa1993 avatar Jan 21 '21 09:01 WanDa1993

解决方案:


                if (firstCompletePosition > 0 && (firstCompletePosition) < items.size()
                        && items.get(firstCompletePosition).isHeader) {

                    View view = mSecondaryLayoutManager.findViewByPosition(firstCompletePosition);
                    if (view != null && view.getTop() <= mTitleHeight) {
                        mTvHeader.setY(view.getTop() - mTitleHeight);
                    }
                } else {
                    //改动二: 如果不进行粘性头的操作时,此时重置Y轴坐标
                    mTvHeader.setY(0);
                }

                // Here is the logic of group title changes and linkage:

                boolean groupNameChanged = false;

                if (mFirstVisiblePosition != firstPosition && firstPosition >= 0) {

                    //改动一: 只判断上滑时,才会重置mTvHeader的Y轴坐标
                    if (mFirstVisiblePosition < firstPosition) {
                        mTvHeader.setY(0);
                    }
                    
                    mFirstVisiblePosition = firstPosition;

   

                    String currentGroupName = items.get(mFirstVisiblePosition).isHeader
                            ? items.get(mFirstVisiblePosition).header
                            : items.get(mFirstVisiblePosition).info.getGroup();

                    if (TextUtils.isEmpty(mLastGroupName) || !mLastGroupName.equals(currentGroupName)) {
                        mLastGroupName = currentGroupName;
                        groupNameChanged = true;
                        mTvHeader.setText(mLastGroupName);
                    }
                }

WanDa1993 avatar Jan 21 '21 09:01 WanDa1993

@Vander-liu

非常感谢你的细心测试和反馈,已提交修改 😉

KunMinX avatar Jan 21 '21 10:01 KunMinX