Вложенная проблема прокрутки RecyclerView

В моем приложении у меня есть вертикальный родительский RecyclerView с несколькими горизонтальными ViewHolders внутри своих ViewHolders. Но у меня довольно неприятная проблема с прокруткой - после того, как я прокрутил родительский RV по вертикали, я хочу прокрутить один из моих дочерних RV, но родитель просто перехватывает все события движения, пока я не удалю палец с экрана, а затем верну его. Вот пример этого раздражающего поведения.

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

Я пробовал каждое решение из этого вопроса - Nested RecyclerView. Как предотвратить прокрутку родительского RecyclerView во время прокрутки дочернего элемента RecyclerView?

Ничто не работает для меня.

Похоже, что в Google Play Market есть такая же иерархия 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;
            }
        }
    }

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

Вы отключили вложенную прокрутку RecyclerView в этой строке

rvUserEvents.setNestedScrollingEnabled(false);

Вам необходимо заменить эту строку ниже на правильную прокрутку

ViewCompat.setNestedScrollingEnabled(rvUserEvents,true);

Ответ 2

Я не заметил этого конкретного поведения, но когда вертикальный RecyclerView, который содержит горизонтально прокручиваемые представления, распахивается, останавливается, RecyclerView держится на сенсорном потоке, поэтому только прокрутка RecyclerView может прокручиваться. Горизонтальные представления не могут прокручиваться до тех пор, пока указатель не будет поднят, а затем снова применен к экрану.

Чтобы обойти это поведение, примените следующий код:

mRecyclerView.addOnItemTouchListener(
        new RecyclerView.SimpleOnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                if (e.getAction() == MotionEvent.ACTION_DOWN
                        && rv.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) {
                    rv.stopScroll();
                }
                return false;
            }
        }
);

Этот код выпустит сенсорный поток из RecyclerView который позволит горизонтально прокручиваемым представлениям сделать снимок при следующем действии перемещения. См. RecyclerView.SimpleOnItemTouchListener.

Ответ 3

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