13

In my application I have vertical parent RecyclerView with few horizontal childs inside its ViewHolders. But I have pretty annoying scrolling issue - after I scroll parent RV vertically I want to scroll one of my child RVs but parent just intercepts all motion events until I remove my finger from screen and then put it back. Here's the example of this annoying behaviour.

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

I tried every solution from this question - Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?

Nothing works for me.

It looks like Google Play Market has the same RV hierarchy, but ofc scroll is perfectly fine. I tried to implement few solutions from other topics, but nothing works as intended.

I don't know what code should I post, but here's my Parent RV's ViewHolder example with nested 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;
            }
        }
    }

EDIT: XML code for my activity

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

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Den
  • 1,284
  • 2
  • 14
  • 33
  • 1
    Your link to the GIF has expired. My Play Store exhibits the behavior that you are seeing in your app. Where, specifically, do you see the alternate behavior in the Play Store app? – Cheticamp Apr 04 '18 at 13:49
  • In the Play Store app you can scroll the parent RV fast, then just put your finger on one of the childs while parent's still scrolling - this action stops parent vertical scrollin and now you can scroll child straight away. As i said, In my application if I scroll parent vertical RV fast I have to put my finger on screen once just to stop parent scrolling, then I have to get my finger off the screen and put it back to scroll child. If I'm tryng to child with my first touch, parent intercepts swipes. @Cheticamp – Den Apr 04 '18 at 13:56
  • Updated gif link @Cheticamp – Den Apr 04 '18 at 14:21
  • Any progress? Any solution? I have same problem. – Kenumir Aug 24 '18 at 07:00
  • From what I understand you need to play around with `MotionEvent`s passing down between `RecyclerView`s. I could probably work on a solution if you can provide a Minimum Verifiable Example. – Abbas Jun 11 '19 at 11:47
  • Please add HomeUserEventsRVAdapter's view holder – Pavya Jun 17 '19 at 05:02
  • Have you all looked at - https://stackoverflow.com/questions/34549414/nested-recyclerview-like-google-play-store-app - 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 Jun 18 '19 at 02:20
  • Try to put child items `RecyclerView` in a `RelativeLayout` or `LinearLayout` – MashukKhan Jun 18 '19 at 03:57

4 Answers4

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

Use android:descendantFocusability="blocksDescendants" attribute inside nested recyclerview

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Rafiqul Hasan
  • 3,324
  • 4
  • 20
  • 28
0

The problem with nested RecyclerView is that the correct slope of the finger fling is not detected correctly.

Here is a snippet of code that actually calculates the correct slope of the fling https://github.com/minarja1/NestedRecyclerSample/blob/developv2/app/src/main/java/com/example/nestedrecyclersample/utils/ViewExtensions.kt

After you add the class to your codebase, you can call the function with a Kotlin Extension.

fun RecyclerView.enforceSingleScrollDirection() {
    val enforcer = SingleScrollDirectionEnforcer()
    addOnItemTouchListener(enforcer)
    addOnScrollListener(enforcer)
}
box
  • 4,450
  • 2
  • 38
  • 38
-1

You disabled the nested scrolling of RecyclerView in this line

rvUserEvents.setNestedScrollingEnabled(false);

You need to replace this line with below to scrolling work properly

ViewCompat.setNestedScrollingEnabled(rvUserEvents,true);
Dhanumjay
  • 540
  • 7
  • 17
  • Well, I did this because I'm using collapsingToolbarLayout with my parent RV. If I remove this line collapsingToolbarLayout will never collapse again. – Den Apr 04 '18 at 13:27
  • 1
    I tried your solution - doesn't work, same behaviour. – Den Apr 04 '18 at 13:30
-3
 recyclerView.setNestedScrollingEnabled(false);