返回

ModalBottomSheetLayout 中使用 LazyColumn 滚动到底部时关闭?如何避免!

Android

在 ModalBottomSheetLayout 中使用 LazyColumn 时避免滚动到底部关闭问题

问题

如果你在 ModalBottomSheetLayout 中使用 LazyColumn 作为可滚动内容,你会发现当你滚动到底部时,ModalBottomSheetLayout 会自动关闭。

问题原因

这是由于 ModalBottomSheetLayout 的默认行为。当其内容可滚动时,它会自动将滚动事件传递给父布局。在我们的情况下,父布局是 NavHost。因此,当 LazyColumn 滚动时,滚动事件会传递给 NavHost,导致 ModalBottomSheetLayout 关闭。

解决方案

为了解决这个问题,我们需要阻止滚动事件传递给父布局。这可以通过使用 Modifier.nestedScroll 修饰符来实现。

LazyColumn(modifier = Modifier.nestedScroll(true)) {
    // ...
}

代码示例

完整的修复后代码如下:

@Destination(style = DestinationStyleBottomSheet::class)
// @Destination
@Composable
fun AppChooserBottomSheet(
    navigator: DestinationsNavigator,
) {
    LazyColumn(modifier = Modifier.nestedScroll(true)) {
        repeat(100) {
            item {
                Text(text = "App $it", style = MaterialTheme.typography.titleLarge, color = neutral100, modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp))
                Log.d("HomePageActivity", "SheetStateAppChooser visible is $it")
            }
        }
    }
}

注意事项

需要注意的是,使用 Modifier.nestedScroll(true) 会禁用 ModalBottomSheetLayout 的拖动关闭功能。如果你需要此功能,你需要实现自己的拖动关闭逻辑。

其他方法

除了使用 Modifier.nestedScroll(true) 之外,还有其他方法可以解决这个问题,例如:

  • 使用 rememberPagerState() 来管理滚动。
  • 使用 GestureDetector() 来检测触摸事件并阻止它们传递给父布局。

这些方法的实现超出了本博客文章的范围,但你可以探索它们以找到最适合你需求的解决方案。

结论

总之,如果你在 ModalBottomSheetLayout 中使用 LazyColumn 并遇到滚动到底部关闭的问题,你可以使用 Modifier.nestedScroll(true) 修饰符来解决。这将阻止滚动事件传递给父布局,从而防止 ModalBottomSheetLayout 关闭。

常见问题解答

  1. 为什么 ModalBottomSheetLayout 默认将滚动事件传递给父布局?
    为了支持父布局中其他组件的滚动。

  2. 除了 Modifier.nestedScroll(true) 之外,还有什么其他方法可以阻止滚动事件传递给父布局?
    可以使用 rememberPagerState() 或 GestureDetector()。

  3. 使用 Modifier.nestedScroll(true) 是否会影响 ModalBottomSheetLayout 的拖动关闭功能?
    是的,会禁用拖动关闭功能。

  4. 在哪些情况下使用 Modifier.nestedScroll(true) 比较合适?
    当你想防止滚动事件传递给父布局并且不需要拖动关闭功能时。

  5. 如果我需要拖动关闭功能,有什么替代方案?
    你可以实现自己的拖动关闭逻辑或使用 GestureDetector() 来检测触摸事件并关闭 ModalBottomSheetLayout。