AppBarLayout RecycleView 点击事件 两次 响应

原文转载自 「掘金Android」 ( https://juejin.im/post/5e7963d2e51d4526d71d69ba ) By 小屁孩_H

预计阅读时间 0 分钟(共 0 个字, 0 张图片, 0 个链接)

复现

开发过程中遇到一个问题,recyclerView 中快速滑动到尾部时,点击无响应,第二次点击生效。

查找原因

首先想到的就是焦点问题。控件中并无主动获取焦点行为的控件,理应没有这种问题,尝试主动获取焦点,无效。

问题最终放到recyclerView本身,监听recyclerView滑动事件输出log查看recyclerView状态。滑动结束后,recyclerView仍然处于滑动状态,尝试在recyclerView中滑动结束后主动设置状态,当dy为正,并且已经完全显示完成,则设置停止。

if (dy > 0) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int visibleItemCount = linearLayoutManager.getChildCount();
int totalItemCount = linearLayoutManager.getItemCount();
int pastVisibleItems = linearLayoutManager.findFirstVisibleItemPosition();

if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
if (!recyclerView.canScrollVertically(1)) {
recyclerView.stopScroll();
}
}
}
复制代码

发现有一定效果,仍然无法完全解决。

由该现象推测,一段时间后,recyclerView状态回归正常。尝试滑动后过一会点击,确实有效,该原因实锤。

搜索引擎检索后查找到有描述和AppBarLayout相关导致。原因是Google在修复滑动时引入的bug,谷歌给出了修复办法。

修复办法地址

解决办法

public class FixAppBarLayoutBehavior extends AppBarLayout.Behavior {

    public FixAppBarLayoutBehavior() {
        super();
    }

    public FixAppBarLayoutBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target,
            int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,
                dxUnconsumed, dyUnconsumed, type);
        stopNestedScrollIfNeeded(dyUnconsumed, child, target, type);
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
            View target, int dx, int dy, int[] consumed, int type) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
        stopNestedScrollIfNeeded(dy, child, target, type);
    }

    private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) {
        if (type == ViewCompat.TYPE_NON_TOUCH) {
            final int currOffset = getTopAndBottomOffset();
            if ((dy < 0 && currOffset == 0)
                    || (dy > 0 && currOffset == -child.getTotalScrollRange())) {
                ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
            }
        }
    }
}
复制代码

在xml或者代码中使用Behavior即可解决该问题

more_vert