我刚刚升级到API 26并支持库26.0.2。但我发现滚动后我的RecyclerView
项目无法点击。如果你等一下,它会起作用。但是如果你立即点击该项目,它就不会。即使RecyclerView
根本没有滚动(例如滚动到顶部)。
当我降级为支持图书馆25.4.0时,一切都恢复正常。
关键点是我的RecyclerView
位于CoordinatorLayout
,SCROLL_FLAG_SCROLL
Toolbar
上有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>
修改
我认为问题是scrollState
的{{1}}。当它停止滚动时,它不会立即更改为RecyclerView
。查看SCROLL_STATE_IDLE
的源代码,我发现有RecyclerView
控制滚动状态。当我向下滚动到顶部时,它不会立即调用ViewFlinger
,而是等待一段时间来触发此方法。我越快,我需要等待的时间越多。就像RecyclerView仍然在后台滚动一样。因为setScrollState(SCROLL_STATE_IDLE)
在scroller.isFinished()
停止滚动到顶部后立即返回true。也许这是RecyclerView
中的RecyclerView
的错误。
答案 0 :(得分:34)
找到一种强制滚动状态为空闲的方法。 等待谷歌修复此错误。
@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
或者在这里使用这个。
答案 1 :(得分:4)
非常感谢您提出这个问题和答案!它为我节省了很多时间。很抱歉发布此答案。我没有足够的声誉来评论。
我也注意到了这个问题,但作为一名新的Android开发人员,我并没有意识到它是新支持库中的一个错误。
我想建议的还是添加此检查:
if( requestCancelDisallowInterceptTouchEvent ){
if (!canScrollVertically(-1) || !canScrollVertically(1)) {
...
}
}
确保在实际滚动RecyclerView时,我们不会点击任何项目。
据我了解,这是一种预期的行为。但是,您的回答帮助了我question。
答案 2 :(得分:0)
我找到了解决此问题的源代码。发生此问题是由于AppBarLayout的行为(AppBarLayout.Behavior)。此源代码提供了AppBarLayout行为的扩展或自定义行为,并通过直接在xml中或java中引入用法将其设置为AppBarLayout。我只能简要解释一下,因为源具有许可证,您也必须阅读该许可证。请在此链接中查看解决方案: https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2