嵌套RecyclerView滚动问题

13

我的应用程序中有一个竖直的父级RecyclerView,里面有几个水平的子项在它的ViewHolders内部。但是我有一个非常烦人的滚动问题-在我垂直滚动父级RV后,我想滚动其中一个子RVs,但父级会拦截所有运动事件,直到我从屏幕上移开手指并重新放回。这是这种令人讨厌的行为的例子。

https://i.imgur.com/dPtmAXD.gif

我尝试了这个问题中的每个解决方案-Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?

对我来说都没用。

看起来谷歌播放市场具有相同的RV层次结构,但滚动当然很好。我尝试从其他主题实现了一些解决方案,但没有按预期工作。

我不知道我应该发布什么代码,但这是我的父级RV ViewHolder示例和嵌套RV。

private class UserEventsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private RecyclerView rvUserEvents;
        private HomeUserEventsRVAdapter rvAdapter;

        public UserEventsViewHolder(View v) {
            super(v);

            rvUserEvents = v.findViewById(R.id.rv_user_events);
            rvUserEvents.setLayoutManager(new LinearLayoutManager(itemView.getContext(), LinearLayoutManager.HORIZONTAL, false));
            rvUserEvents.setNestedScrollingEnabled(false);
            rvUserEvents.setRecycledViewPool(viewPool);
            rvAdapter = new HomeUserEventsRVAdapter(presenter);
            rvUserEvents.setAdapter(rvAdapter);

            v.findViewById(R.id.btn_all_user_events).setOnClickListener(this);
        }

        private void bind(UserItemViewModel userItem) {
            rvAdapter.updateAdapter(userItem);
        }

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_all_user_events:
                    presenter.openUserEventsList();
                    break;
            }
        }
    }

编辑:我的活动的XML代码

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">

<android.support.design.widget.AppBarLayout
    android:id="@+id/ab_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:fitsSystemWindows="true">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="190dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        android:fitsSystemWindows="true"
        app:contentScrim="@android:color/white"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginEnd="64dp">

        <ImageView
            android:id="@+id/iv_pic"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:src="@drawable/ic_home_screen_background"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.5"/>

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:elevation="7dp"
            android:theme="@style/ToolbarTheme"
            app:layout_collapseMode="pin"/>
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/sr_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="-6dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_results"
        android:clipToPadding="false"
        android:scrollbars="vertical"
        android:scrollbarThumbVertical="@color/orange_juice_80"
        android:scrollbarSize="2dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/shape_rounded_top_grey"
        android:fitsSystemWindows="true" />
</android.support.v4.widget.SwipeRefreshLayout>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_add"
    android:layout_width="56dp"
    android:layout_height="56dp"
    android:layout_marginEnd="15dp"
    app:backgroundTint="@color/dark_background"
    app:layout_anchor="@id/rv_results"
    app:layout_anchorGravity="top|right|end"
    app:layout_scrollFlags="scroll|exitUntilCollapsed"
    app:srcCompat="@drawable/ic_vector_plus_white" />


1
您的 GIF 链接已过期。我的 Play Store 出现了您在应用中看到的行为。您在 Play Store 应用程序中具体在哪里看到了替代行为? - Cheticamp
在Play Store应用程序中,您可以快速滚动父RV,然后在父级仍在滚动时将手指放在其中一个子级上 - 此操作会停止父级垂直滚动,现在您可以立即滚动子级。正如我所说,在我的应用程序中,如果我快速滚动父垂直RV,则必须先在屏幕上放置手指以停止父滚动,然后必须将手指离开屏幕并重新放置以滚动子级。如果我尝试使用第一次触摸来控制子级,则父级会拦截滑动。@Cheticamp - Den
更新的gif链接@Cheticamp - Den
有进展了吗? 有解决方案吗? 我也遇到了同样的问题。 - Kenumir
大家是否已经看过以下内容:
  • https://dev59.com/91sW5IYBdhLWcg3w0Z_L
  • https://github.com/Ranjan101/RecyclerView-Google-Play
  • http://khmertechtrain.tk/index.php/2017/10/03/create-a-vertical-scroll-and-horizontal-scroll-app-like-google-play-store/
- nishon.tan
显示剩余3条评论
4个回答

0

嵌套RecyclerView的问题在于无法正确检测到手指滑动的正确斜率。

这里是一段代码片段,实际上计算了快速滑动的正确斜率 https://github.com/minarja1/NestedRecyclerSample/blob/developv2/app/src/main/java/com/example/nestedrecyclersample/utils/ViewExtensions.kt

将该类添加到您的代码库后,您可以使用Kotlin扩展调用该函数。

fun RecyclerView.enforceSingleScrollDirection() {
    val enforcer = SingleScrollDirectionEnforcer()
    addOnItemTouchListener(enforcer)
    addOnScrollListener(enforcer)
}

0
<androidx.recyclerview.widget.RecyclerView
     android:id="@+id/recyclerView"
     android:layout_width="match_parent"
     android:descendantFocusability="blocksDescendants"
     android:layout_height="wrap_content"
     android:scrollbars="none" />

在嵌套的RecyclerView中使用android:descendantFocusability="blocksDescendants"属性


-1

您在此行禁用了RecyclerView的嵌套滚动

rvUserEvents.setNestedScrollingEnabled(false);

您需要将此行替换为以下内容,以使滚动正常工作

ViewCompat.setNestedScrollingEnabled(rvUserEvents,true);

我这样做是因为我正在使用带有父RV的collapsingToolbarLayout。如果我删除此行,collapsingToolbarLayout将永远不会再次折叠。 - Den
1
我尝试了你的解决方案 - 不起作用,行为相同。 - Den

-3
 recyclerView.setNestedScrollingEnabled(false);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接