しんえつ 2024-08-08 12:47 采纳率: 0%
浏览 24
已结题

Bottom sheet与内嵌的fragment滚动冲突

我有一个FragmentA和FragmentB
FragmentA的layout中有一个LinearLayout 它的behaviour设置成了BottomSheetBehaviour用来显示成一个BottmSheet
在它里面我装了一个FragmentContainerView (id:container)
在FragmentA中有一个功能是点击某个按钮之后 把container替换成FragmentB 实现在bottomSheet中显示FragmentB的内容
fragmentB的layout是使用compose写的 里面有一个lazyColumn所以它本身可以滚动
我遇到的问题是
因为bottomsheet和fragmentB都能用手指滑动改变显示位置 当我把bottomSheet滑动到全屏幕显示之后 继续向上滑动 会触发内部的FragmentB滑动 直到显示FragmentB最底层的内容(到这里没有问题)
但是在这个状态下 我向下滑动屏幕 bottmsheet先被滑动 直到滑动到最底部它消失 内部的fragmentB无法滑动
我如何实现 在BottomSheet全屏显示的情况下 向下滑动手指时 先滑动内部的FragmentB 直到FragmentB的顶部内容都显示出来了 再滑动BottomSheet

  • 写回答

21条回答 默认 最新

  • hb13262736769 2024-08-08 17:56
    关注
    回答来自于wx公众号:一休哥助手
    

    要解决 Bottom Sheet 与内部 Fragment 的滚动冲突问题,可以尝试以下方法。这个方法是基于协调布局行为的思想,通过设置不同的滚动优先级来解决滚动冲突。

    我们可以利用 CoordinatorLayoutBottomSheetBehavior,结合 NestedScrollViewNestedScrollingChild 接口来实现这个功能。这个思路是,当 BottomSheet 在全屏显示时,将内部 Fragment 的滚动优先级提升,当内部 Fragment 滚动到顶端时,再恢复 BottomSheet 的滚动。

    1. 使用 CoordinatorLayoutBottomSheetBehavior

    确保你的 FragmentA 使用了 CoordinatorLayout,并且 BottomSheet 的布局设置了 BottomSheetBehavior

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <LinearLayout
            android:id="@+id/bottom_sheet"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
            
            <FragmentContainerView
                android:id="@+id/container"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
            
        </LinearLayout>
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    2. 处理滚动冲突

    FragmentB 中,使用 NestedScrollView 或实现 NestedScrollingChild 接口来处理内部的滚动。

    如果你使用的是 Jetpack Compose,那么你可以使用 Modifier.nestedScroll 来处理内部滚动。

    3. 监听 BottomSheet 状态

    FragmentA 中,监听 BottomSheet 的状态,并相应地调整滚动行为。

    class FragmentA : Fragment() {
    
        private lateinit var bottomSheetBehavior: BottomSheetBehavior<LinearLayout>
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val view = inflater.inflate(R.layout.fragment_a, container, false)
    
            val bottomSheet = view.findViewById<LinearLayout>(R.id.bottom_sheet)
            bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
    
            // Replace fragment when button is clicked
            val button = view.findViewById<Button>(R.id.button)
            button.setOnClickListener {
                childFragmentManager.beginTransaction()
                    .replace(R.id.container, FragmentB())
                    .commit()
            }
    
            return view
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
                override fun onStateChanged(bottomSheet: View, newState: Int) {
                    // Handle state changes
                }
    
                override fun onSlide(bottomSheet: View, slideOffset: Float) {
                    // Handle sliding
                }
            })
        }
    }
    

    4. 在 FragmentB 中使用 Compose 的 NestedScroll

    如果你在 FragmentB 中使用 Jetpack Compose,那么可以如下设置滚动处理:

    class FragmentB : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return ComposeView(requireContext()).apply {
                setContent {
                    val nestedScrollConnection = remember {
                        object : NestedScrollConnection {
                            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                                // Check BottomSheet state and handle scroll
                                return Offset.Zero
                            }
                        }
                    }
    
                    LazyColumn(
                        modifier = Modifier
                            .fillMaxSize()
                            .nestedScroll(nestedScrollConnection)
                    ) {
                        items(100) {
                            Text(text = "Item #$it", modifier = Modifier.padding(16.dp))
                        }
                    }
                }
            }
        }
    }
    

    总结

    以上方法结合了 CoordinatorLayoutBottomSheetBehaviorNestedScrollViewNestedScrollingChild 接口,通过监听 BottomSheet 的状态来动态调整内部 Fragment 的滚动行为,以解决滚动冲突问题。在 Compose 中,可以通过 Modifier.nestedScroll 来实现类似效果。

    这些方法可以帮助你在 Bottom Sheet 全屏显示时优先滚动内部的 Fragment,当内部 Fragment 滚动到顶端时再滚动 Bottom Sheet。

    评论

报告相同问题?

问题事件

  • 系统已结题 8月16日
  • 修改了问题 8月8日
  • 创建了问题 8月8日

悬赏问题

  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见
  • ¥15 一共有五道问题关于整数幂的运算还有房间号码 还有网络密码的解答?(语言-python)
  • ¥20 sentry如何捕获上传Android ndk 崩溃
  • ¥15 在做logistic回归模型限制性立方条图时候,不能出完整图的困难
  • ¥15 G0系列单片机HAL库中景园gc9307液晶驱动芯片无法使用硬件SPI+DMA驱动,如何解决?