我有一个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
Bottom sheet与内嵌的fragment滚动冲突
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
21条回答 默认 最新
hb13262736769 2024-08-08 17:56关注回答来自于wx公众号:一休哥助手要解决 Bottom Sheet 与内部 Fragment 的滚动冲突问题,可以尝试以下方法。这个方法是基于协调布局行为的思想,通过设置不同的滚动优先级来解决滚动冲突。
我们可以利用
CoordinatorLayout和BottomSheetBehavior,结合NestedScrollView或NestedScrollingChild接口来实现这个功能。这个思路是,当BottomSheet在全屏显示时,将内部Fragment的滚动优先级提升,当内部Fragment滚动到顶端时,再恢复BottomSheet的滚动。1. 使用
CoordinatorLayout和BottomSheetBehavior确保你的
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)) } } } } } }总结
以上方法结合了
CoordinatorLayout、BottomSheetBehavior和NestedScrollView或NestedScrollingChild接口,通过监听BottomSheet的状态来动态调整内部Fragment的滚动行为,以解决滚动冲突问题。在Compose中,可以通过Modifier.nestedScroll来实现类似效果。这些方法可以帮助你在 Bottom Sheet 全屏显示时优先滚动内部的 Fragment,当内部 Fragment 滚动到顶端时再滚动 Bottom Sheet。
解决 无用评论 打赏 举报