Android - 滚动后无法单击 RecyclerView 中的项目 [英] Android - the item inside RecyclerView can't be clicked after scroll

查看:26
本文介绍了Android - 滚动后无法单击 RecyclerView 中的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚升级到 API 26 并支持库 26.0.2.但我发现我的 RecyclerView 项目在滚动后不可点击.如果你等一下,它就会起作用.但是,如果您立即单击该项目,则不会.即使 RecyclerView 根本没有滚动(例如已经滚动到顶部).

当我降级到支持库 25.4.0 时,一切又正常了.关键是我的 RecyclerView 位于 CoordinatorLayout 中,并且在 ToolbarToolbar 上有一个 SCROLL_FLAG_SCROLL 标志代码>AppBarLayout.如果我不使用这个标志,那么这个问题就会消失.所以我认为这是支持库26的隐藏行为变化.

我尝试将 focusable="false" 添加到 CoordinatorLayout 但仍然没有运气.

有什么办法可以禁用这种行为吗?因为点击两次触发点击事件真的很烦.

 <android.support.design.widget.AppBarLayoutandroid:id="@+id/fragmentAppBar"android:layout_width="match_parent"android:layout_height="wrap_content"应用程序:海拔=0dp"android:background="@null"><包括android:id="@+id/dynamicActionBarHolder"layout="@layout/dynamic_action_bar"/></android.support.design.widget.AppBarLayout><android.support.v4.widget.SwipeRefreshLayoutandroid:id="@+id/pullToRefreshMailRecycler"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"><android.support.v7.widget.RecyclerViewandroid:id="@+id/mailRecyclerView"android:layout_width="match_parent"android:layout_height="match_parent"/></android.support.v4.widget.SwipeRefreshLayout></android.support.design.widget.CoordinatorLayout>

编辑

我认为问题在于RecyclerViewscrollState.当它停止滚动时,它不会立即更改为 SCROLL_STATE_IDLE.查看 RecyclerView 的源代码,我发现有一个 ViewFlinger 控制滚动状态.当我向下滚动到顶部时,它不会立即调用 setScrollState(SCROLL_STATE_IDLE) ,而是等待一段时间来触发此方法.我飞得越快,我需要等待的时间就越多.就像 RecyclerView 仍在后台滚动一样.因为 scroller.isFinished()RecyclerView 触及顶部后停止滚动后不会立即返回 true .可能是 RecyclerViewCoordinatorLayout 中的一个 bug.

解决方案

找到了强制滚动状态为空闲的方法.等待谷歌修复这个错误.

@Override公共布尔 onInterceptTouchEvent(MotionEvent 事件) {boolean requestCancelDisallowInterceptTouchEvent = getScrollState() == SCROLL_STATE_SETTLING;布尔消耗 = super.onInterceptTouchEvent(event);final int action = event.getActionMasked();开关(动作){案例 MotionEvent.ACTION_DOWN:if( requestCancelDisallowInterceptTouchEvent ){getParent().requestDisallowInterceptTouchEvent(false);//仅当它触及顶部或底部时.感谢@Sergey 的回答.if (!canScrollVertically(-1) || !canScrollVertically(1)) {//停止滚动以启用子视图获取触摸事件停止滚动();//不消费事件返回假;}}休息;}消费回报;}

编辑

该问题已在支持库 27.0.1 中修复.

https://developer.android.com/topic/libraries/support-library/revisions.html#27-0-1

<块引用>

用户滚动后,他们无法点击 RecyclerView 中的项目.(AOSP 问题 66996774)

2017 年 11 月 17 日更新

一些用户报告说这个问题在支持库 27.0.1 中没有修复.问题跟踪器在这里.https://issuetracker.google.com/issues/66996774

因此您可以选择使用此官方解决方法.https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed>2

或者在这里使用这个.

I just upgraded to API 26 and support library 26.0.2. But I found that my RecyclerView items is not clickable right after the scrolling. If you wait for a second, it will work. But if you click the item immediately, it won't. Even if the RecyclerView is not scrolling at all(e.g. has scrolled to the top).

When I downgraded to support library 25.4.0 everything goes fine again. The key point is that my RecyclerView is in a CoordinatorLayout and has a SCROLL_FLAG_SCROLL flag on my Toolbar of the AppBarLayout. If I don't use this flag, then this problem will disappear. So I think it's a hidden behavior change of support library 26.

I've tried to add focusable="false" to the CoordinatorLayout but still had no luck.

Is there any way to disable this behavior? Because it's really annoying to click twice to trigger the click event.

 <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinateLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
            android:id="@+id/fragmentAppBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:elevation="0dp"
            android:background="@null">
        <include
                android:id="@+id/dynamicActionBarHolder"
                layout="@layout/dynamic_action_bar"/>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/pullToRefreshMailRecycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v7.widget.RecyclerView
                android:id="@+id/mailRecyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

    </android.support.v4.widget.SwipeRefreshLayout>

</android.support.design.widget.CoordinatorLayout>

EDIT

I think the problem is the scrollState of the RecyclerView. When it's stopped scrolling, it's not changed to SCROLL_STATE_IDLE immediately. Looking into the source code of RecyclerView, I found there's a ViewFlinger controlling the scroll state. When I fling down to scroll to the top, it's not calling setScrollState(SCROLL_STATE_IDLE) immediately, instead, it wait for a while to trigger this method. The more fast I fling, the more time I need to wait. It just like the RecyclerView is still scrolling in the background. Because the scroller.isFinished() doesn't return true right after the RecyclerView stop scrolling when it touched the top. Maybe it's a bug of the RecyclerView when it's in a CoordinatorLayout.

解决方案

Found a way to force the scroll state to be idle. Waiting for google to fix this bug.

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean requestCancelDisallowInterceptTouchEvent = getScrollState() == SCROLL_STATE_SETTLING;
    boolean consumed = super.onInterceptTouchEvent(event);
    final int action = event.getActionMasked();

    switch (action) {
        case MotionEvent.ACTION_DOWN:
            if( requestCancelDisallowInterceptTouchEvent ){
                getParent().requestDisallowInterceptTouchEvent(false);

                // only if it touched the top or the bottom. Thanks to @Sergey's answer.
                if (!canScrollVertically(-1) || !canScrollVertically(1)) {
                    // stop scroll to enable child view to get the touch event
                    stopScroll();
                    // do not consume the event
                    return false;
                }
            }
            break;
    }

    return consumed;
}

EDIT

The issue has been fixed in support library 27.0.1.

https://developer.android.com/topic/libraries/support-library/revisions.html#27-0-1

After a user scrolls, they cannot click on an item in a RecyclerView. (AOSP issue 66996774)

Updated on Nov 17, 2017

Some users reported that this problem is not fixed in support library 27.0.1. The issue tracker is here. https://issuetracker.google.com/issues/66996774

So you may choose to use this official workaround. https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2

Or use this one here.

这篇关于Android - 滚动后无法单击 RecyclerView 中的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆