简体   繁体   中英

How to enable dragging on ViewPager2 inside BottomSheetDialogFragment?

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.

The main issue is that the ViewPager2 RecyclerView is not accessible by default. The good news is that 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);

That worked for me, but if still there are issues, then try to disable the over scroll mode:

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

Preview:

If you use STATE_EXPANDED mode is default mode and hideable property is true,you can not drag it down.

So set BottomSheetBehavior.STATE_COLLAPSED is default mode and set hideable,PeakHight property.

 <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="@drawable/bottom_sheet_background"
        android:orientation="vertical"
        app:layout_behavior="@string/bottom_sheet_behavior"
        
        app:behavior_peekHeight="500dp"
         app:behavior_hideable="false"

        android:clickable="true"
    android:focusable="true">

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM