Reputation: 1352
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" />
Upvotes: 13
Views: 7738
Reputation: 1
Bit late but want to share so that if someone suffer from this in future.
If you're using XML specifically ConstraintLayout for your UI -> then use RelativeLayout for specific recyclerview child. write recyclerview (androidx.recyclerview.widget.RecyclerView) inside RelativeLayout. it scrolls smothly with RelativeLayout.
you'll not require any extra tag or attribute For instance:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<androidx.core.widget.NestedScrollView
android:fillViewport="true"
android:id="@+id/nestedView"
android:layout_height="match_parent"
android:layout_marginTop="40dp"
android:layout_width="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
.
.
.
<RelativeLayout
android:id="@+id/rvPasser1"
android:layout_height="wrap_content"
android:layout_width="match_parent"
app:layout_constraintTop_toBottomOf="@+id/llPassingFromMenuA">
<androidx.recyclerview.widget.RecyclerView
android:background="@drawable/list_box"
android:id="@+id/rv"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
</RelativeLayout>
.
.
.
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Upvotes: 0
Reputation: 4688
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)
}
Upvotes: 0
Reputation: 3622
<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
Upvotes: 0
Reputation: 525
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);
Upvotes: -1