There's a BottomSheetDialogFragment
and working good vertically dragging states on fragment layout and opening STATE_EXPANDED
mode. There's a recyclerview
inside it and dragging vertically works on the bottom sheet but it doesn't work on recyclerview
because of scrolling event. How the bottom sheet dragging event to work instead of scroll event on recyclerview
when reached top of list and still scrolling up for collapse the bottom sheet?
BottomSheetDialogFragment hierarchy:
FragmentRootLinearLayout -> ...BottomLinearLayout... -> ViewPager2 -> RecyclerView
BottomSheetDialogFragment xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/BookInfoFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/tool_sheet_bg"
android:orientation="vertical"
app:layout_behavior="@string/bottom_sheet_behavior"
app:behavior_hideable="true"
android:clickable="true"
android:focusable="true">
<LinearLayout
android:id="@+id/tabs_linear_layout"
style="@style/ThemeSettingsRowContainer"
android:layout_width="match_parent"
android:layout_height="550dp"
android:layout_marginTop="15dp"
android:background="@drawable/xml_rounded_corner_bg2"
android:clickable="true"
android:focusable="true"
android:paddingTop="0dp"
android:paddingBottom="0dp">
<com.google.android.material.tabs.TabLayout
android:id="@+id/book_loading_tablayout"
android:layout_width="match_parent"
android:layout_height="50dp" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/book_loading_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true" />
</LinearLayout>
</LinearLayout>
Edit: The issue is on ViewPager2, when I change it to ViewPager dragging is working good on it. Same issue: BottomSheet + ViewPager2 drag to hide not works
The issue is that we need to disable the nested scrolling on the ViewPager2
, but the android:nestedScrollingEnabled="false"
doesn't work because ViewPager2
is functioning internally using RecyclerView
which has the effect of the nested scrolling.
So, you need to disable the nested scrolling of the ViewPager
RecyclerView
.
The main issue is that the RecyclerView
of ViewPager2
is not accessible by default.
Update Feb.2022
Adding a better way to access the
RecyclerView
of theViewPager2
instead of using reflections:
Kotlin:
viewPager2.children.find { it is RecyclerView }?.let {
(it as RecyclerView).isNestedScrollingEnabled = false
}
Java:
for (int i = 0; i < viewPager2.getChildCount(); i++) {
View child = mViewPager.getChildAt(i);
if (child instanceof RecyclerView)
((RecyclerView) child).setNestedScrollingEnabled(false);
}
This should work, but if still facing issues, then try to disable the over scroll mode of the RecyclerView
:
// Kotlin
recyclerView?.overScrollMode = View.OVER_SCROLL_NEVER // Optional
// Java
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER); // Optional
Preview:
You can access it using java reflection.
And this requires to know the name field of the RecyclerView
which can be found in the ViewPager2
definition class which is mRecyclerView
Combining that together in a helper function:
public static RecyclerView getRecyclerView(ViewPager2 viewPager) {
try {
Field field = ViewPager2.class.getDeclaredField("mRecyclerView");
field.setAccessible(true);
return (RecyclerView) field.get(viewPager);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
Then you can disable the nested scrolling as follows:
RecyclerView recyclerView = getRecyclerView(viewPager);
if (recyclerView != null)
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
For Kotlin users:
Extension function:
fun ViewPager2.getRecyclerView(): RecyclerView? {
try {
val field = ViewPager2::class.java.getDeclaredField("mRecyclerView")
field.isAccessible = true
return field.get(this) as RecyclerView
} catch (e: NoSuchFieldException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
return null
}
And usage:
val recyclerView = viewPager.getRecyclerView()
recyclerView?.isNestedScrollingEnabled = false
recyclerView?.overScrollMode = View.OVER_SCROLL_NEVER // Optional
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With