Android - 滚动后无法单击RecyclerView中的项目

问题描述 投票:28回答:3

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

当我降级为支持库25.4.0时,一切都会好起来的。关键点是我的RecyclerViewCoordinatorLayout并且在我的SCROLL_FLAG_SCROLLToolbar上有一个AppBarLayout旗。如果我不使用此标志,则此问题将消失。所以我认为这是支持库26的隐藏行为变化。

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

有没有办法禁用这种行为?因为点击两次触发点击事件真的很烦人。

 <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>

编辑

我认为问题是scrollStateRecyclerView。当它停止滚动时,它不会立即更改为SCROLL_STATE_IDLE。查看RecyclerView的源代码,我发现有一个控制滚动状态的ViewFlinger。当我向下滚动到顶部时,它不会立即调用setScrollState(SCROLL_STATE_IDLE),而是等待一段时间来触发此方法。我越快,我需要等待的时间越多。就像RecyclerView仍然在后台滚动一样。因为当scroller.isFinished()触及顶部时RecyclerView停止滚动后,RecyclerView不会返回true。也许这是CoordinatorLayout的一个错误,当它在@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; } 时。

android android-recyclerview android-support-library android-coordinatorlayout
3个回答
34
投票

找到了一种强制滚动状态为空闲的方法。等待谷歌修复此错误。

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

编辑

该问题已在支持库27.0.1中得到修复。

https://issuetracker.google.com/issues/66996774

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

2017年11月17日更新

一些用户报告在支持库27.0.1中没有修复此问题。问题跟踪器在这里。 https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2

因此,您可以选择使用此官方解决方法。 if( requestCancelDisallowInterceptTouchEvent ){ if (!canScrollVertically(-1) || !canScrollVertically(1)) { ... } }

或者在这里使用这个。


4
投票

非常感谢您提出这个问题和答案!它为我节省了很多时间。很抱歉发布此答案。我没有足够的声誉来发表评论。

我也注意到了这个问题,但作为一个新的Android开发人员,我没有意识到这是新支持库中的一个错误。

我想建议的还是添加这个检查:

question

它将确保在RecyclerView实际滚动时,我们不会点击任何项目。

据我了解,这是一种预期的行为。但是,你的回答帮助了我这个https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2


0
投票

我找到了解决此问题的源代码。出现此问题是因为AppBarLayout的行为(AppBarLayout.Behavior)。此源代码提供AppBarLayout行为的扩展或自定义行为,并将其设置为AppBarLayout,并在xml中直接引入或使用java。我只能简单地解释它,因为源有许可证,你必须阅读它。请参阅此链接中的解决方案:qazxswpoi

© www.soinside.com 2019 - 2024. All rights reserved.