【问题标题】:Android - the item inside RecyclerView can't be clicked after scrollAndroid - 滚动后无法点击 RecyclerView 内的项目
【发布时间】:2017-09-27 16:04:20
【问题描述】:

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

当我降级以支持库 25.4.0 时,一切都恢复正常了。 关键是我的RecyclerViewCoordinatorLayout 中,并且在ToolbarAppBarLayout 上有一个SCROLL_FLAG_SCROLL 标志。如果我不使用这个标志,那么这个问题就会消失。所以我认为这是支持库 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>

编辑

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

【问题讨论】:

  • 能否删除SwipeRefreshLayout 中的app:layout_behavior再试一次?
  • 滚动后仍然无法点击。使其工作的唯一方法是将标志设置为 0,setScrollFlags(0)

标签: android android-recyclerview android-support-library android-coordinatorlayout


【解决方案1】:

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

@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;
}

编辑

该问题已在支持库 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/8391b5adb9ee42180893300850ed02f2

或者在这里使用这个。

【讨论】:

  • The issue has been fixed in support library 27.0.1. 这实际上并没有为我解决它:P 27.0.2(还没有时间解决变通办法)
  • @EpicPandaForce 我们都知道谷歌不擅长修复错误。我仍在等待他们修复导致我的应用程序每天崩溃 200 次的 chromium 错误。已经快一年了。
  • 不擅长修复错误不是问题,开发人员确实手动修复了它。问题是谷歌也擅长制造错误。你知道,我害怕更新 Google 的 API。
  • @nyconing 完全同意你的看法。这总是一场灾难。
  • 我没有使用坐标布局和AppBarLayout,在Relativelayout中有水平recylerview。我有一个要求,因为recylerview需要自动滚动,需要在屏幕中找到中心项目,还需要在滚动时单击项目。我已经实现了自动滚动。但是单击不起作用的项目。我在这里提出了一个问题,stackoverflow.com/questions/51959211/…
【解决方案2】:

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

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

我想建议的也是添加此检查:

if( requestCancelDisallowInterceptTouchEvent ){
    if (!canScrollVertically(-1) || !canScrollVertically(1)) {
        ...
    }
}

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

据我了解,这是一种预期行为。但是,您的回答帮助了我question

【讨论】:

  • 你是对的。我正在使用LayoutManagerfindFirstCompletelyVisibleItemPositionfindLastCompletelyVisibleItemPosition 来检查我的RecyclerView 是否已经滚动到顶部或底部。不知道有canScrollVertically 方法。这比使用LayoutManager 更优雅。
  • 嗨@KimiChiu!再一次,我只能对我的回答发表评论:) 嘿!看起来他们已经在修订版 27.0.1 中修复了这个错误。我敢打赌这是你的报告issuetracker.google.com/issues/66996774 :)) 至少电子邮件以“ki...@gmail.com”开头
  • 看起来问题在 27.0.1 中仍然存在。我已经根据您的建议编辑了我的答案,以防有人遇到同样的问题。
【解决方案3】:

我找到了解决此问题的源代码。由于 AppBarLayout 的行为 (AppBarLayout.Behavior) 会出现此问题。此源代码提供了 AppBarLayout 行为的扩展或自定义行为,并将其设置到 AppBarLayout 中,并直接在 xml 或 java 中引入使用。我只能简要解释一下,因为来源有许可证,你也必须阅读它。请参阅此链接中的解决方案: https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2

【讨论】:

    猜你喜欢
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多