【问题标题】:How to enable dragging on ViewPager2 inside BottomSheetDialogFragment?如何在 BottomSheetDialogFragment 内的 ViewPager2 上启用拖动?
【发布时间】:2021-05-29 08:51:26
【问题描述】:

在片段布局和打开STATE_EXPANDED 模式上有一个BottomSheetDialogFragment 和工作良好的垂直拖动状态。里面有一个recyclerview,垂直拖动在底部工作表上有效,但由于滚动事件,它不适用于recyclerview。当到达列表顶部并且仍然向上滚动以折叠底部工作表时,底部工作表拖动事件如何工作而不是 recyclerview 上的滚动事件?

BottomSheetDialogFragment 层次结构:

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>

编辑: 问题出在 ViewPager2 上,当我将其更改为 ViewPager 时,拖动效果很好。同样的问题:BottomSheet + ViewPager2 drag to hide not works

【问题讨论】:

  • 添加你的xml代码@ATES
  • 就是这样。
  • 所以当您到达列表顶部时,您正试图向下拖动底部工作表,但它没有折叠,而是回收站视图仍在滚动?我说的对吗?@ATES
  • 是的,你是对的,并且 recyclerview onScrollEvent 没有处理,因为从顶部滚动完成。

标签: java android android-layout android-recyclerview


【解决方案1】:

问题是我们需要禁用ViewPager2 上的嵌套滚动,但android:nestedScrollingEnabled="false" 不起作用,因为ViewPager2 在内部使用RecyclerView 运行,它具有嵌套滚动的效果。

因此,您需要禁用 ViewPager RecyclerView 的嵌套滚动。

主要问题是ViewPager2RecyclerView默认是不可访问的。

2022 年 2 月更新

添加一个更好的方式来访问ViewPager2RecyclerView 而不是使用反射:

科特林:

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);
}

这应该可以,但如果仍然遇到问题,请尝试禁用 RecyclerView 的过度滚动模式:

// Kotlin
recyclerView?.overScrollMode = View.OVER_SCROLL_NEVER // Optional
// Java
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER); // Optional

预览:


有反射 ----

您可以使用java reflection 访问它。

这需要知道RecyclerView 的名称字段,可以在ViewPager2 定义类中找到,即mRecyclerView

将它们组合成一个辅助函数:

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;
}

然后你可以禁用嵌套滚动如下:

RecyclerView recyclerView = getRecyclerView(viewPager);
if (recyclerView != null)
    recyclerView.setNestedScrollingEnabled(false);
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);

对于 Kotlin 用户:

扩展功能:

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
}

及用法:

val recyclerView = viewPager.getRecyclerView()
recyclerView?.isNestedScrollingEnabled = false
recyclerView?.overScrollMode = View.OVER_SCROLL_NEVER // Optional

【讨论】:

  • 谢谢,工作,但为什么向上滚动不能在 recyclerview 上工作?
  • @ATES 你是指ViewPager2 的RecyclerView 还是BottomSheet 中有另一个RecyclerView
  • 我的意思是 ViewPager2 上的 RC,向下滚动有效但向上不工作,拖动底页而不是向上滚动。
  • 当我在向下滚动后向上滚动时效果很好,但如果我在等待一段时间后向上滚动(完成滚动后)它就不起作用:)
  • @ATES 我已经厌倦了 ViewPager1 这似乎是 ViewPager 1、2 中的默认行为 ..希望我能把你弄好..恐怕我没有得到你能不能给我看个 gif 让我更明白
【解决方案2】:

如果你使用STATE_EXPANDED模式是默认模式,并且hideable属性为true,你不能拖下来。

所以设置 BottomSheetBehavior.STATE_COLLAPSED 为默认模式并设置 hideable ,PeakHight 属性。

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

【讨论】:

  • 对我不起作用,TabLayout 和所有区域都是可拖动的,除了 ViewPager2,所有问题都在它上面。我已经删除了recyclerview,它是空的,但仍然不能拖动。我找不到它的任何属性。
  • 当我将 viewpager2 更改为 viewpager 时效果很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 2017-07-06
  • 1970-01-01
  • 1970-01-01
  • 2023-02-08
  • 2011-06-24
相关资源
最近更新 更多