You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BottomSheetScaffold修改remember状态后首次无法展开,需点击屏幕才生效的解决方法

问题:BottomSheetScaffold修改模糊状态后首次无法展开

我需要在BottomSheetScaffold展开时模糊屏幕背景,但在展开底部弹窗前修改remembered状态值isBlurred后,底部弹窗首次尝试无法展开,只有点击屏幕任意位置后才会打开。请问如何解决该问题?

原代码

@Composable
fun MyScreen() {
   val sheetState = SheetState(skipHiddenState = false, skipPartiallyExpanded = false)
   val sheetController = rememberBottomSheetScaffoldState(sheetState)
   var isBlurred by remember { mutableStateOf(false) }
   val blur by animateDpAsState(targetValue = if (isBlurred) 10.dp else 0.dp)
   val scope = rememberCoroutineScope()

   Box (modifier = Modifier.blur(radius = blur).fillMaxSize()) {
      ElevatedButton(onClick = {
          scope.launch {
              isBlurred = true
              sheetController.bottomSheetState.expand() // 无法展开
          }
      }) {
          Text("Blur")
      }
   }

   BottomSheetScaffold(
        scaffoldState = sheetController,
        sheetContent = { /* 自定义内容 */ },
        sheetDragHandle = {},
        sheetContainerColor = Color.Transparent,
        sheetShadowElevation = 0.dp,
        sheetSwipeEnabled = false
    ) {}
}

解决方案

问题根源是修改isBlurred触发Compose重组,导致BottomSheetScaffold的状态在重组过程中被干扰,expand()的协程执行时机和重组冲突,导致首次展开失效。以下两种方法可解决该问题:

方法1:将BottomSheetScaffold嵌套在模糊Box内部

把BottomSheetScaffold放到负责模糊的Box里面,确保弹窗状态和模糊效果的重组上下文一致:

@Composable
fun MyScreen() {
   val sheetState = SheetState(skipHiddenState = false, skipPartiallyExpanded = false)
   val sheetController = rememberBottomSheetScaffoldState(sheetState)
   var isBlurred by remember { mutableStateOf(false) }
   val blur by animateDpAsState(targetValue = if (isBlurred) 10.dp else 0.dp)
   val scope = rememberCoroutineScope()

   Box(modifier = Modifier.blur(radius = blur).fillMaxSize()) {
      ElevatedButton(onClick = {
          scope.launch {
              isBlurred = true
              sheetController.bottomSheetState.expand()
          }
      }) {
          Text("Blur")
      }

      // 将BottomSheetScaffold移到Box内部
      BottomSheetScaffold(
          scaffoldState = sheetController,
          sheetContent = { /* 自定义内容 */ },
          sheetDragHandle = {},
          sheetContainerColor = Color.Transparent,
          sheetShadowElevation = 0.dp,
          sheetSwipeEnabled = false
      ) {}
   }
}

方法2:用LaunchedEffect监听isBlurred状态变化

通过LaunchedEffect监听isBlurred的变化,当状态变为true时自动展开弹窗,避免在点击回调中同时修改状态和执行展开操作:

@Composable
fun MyScreen() {
   val sheetState = SheetState(skipHiddenState = false, skipPartiallyExpanded = false)
   val sheetController = rememberBottomSheetScaffoldState(sheetState)
   var isBlurred by remember { mutableStateOf(false) }
   val blur by animateDpAsState(targetValue = if (isBlurred) 10.dp else 0.dp)
   val scope = rememberCoroutineScope()

   // 监听isBlurred变化,自动展开弹窗
   LaunchedEffect(isBlurred) {
       if (isBlurred) {
           sheetController.bottomSheetState.expand()
       }
   }

   Box(modifier = Modifier.blur(radius = blur).fillMaxSize()) {
      ElevatedButton(onClick = {
          isBlurred = true // 只修改状态,展开逻辑交给LaunchedEffect
      }) {
          Text("Blur")
      }
   }

   BottomSheetScaffold(
        scaffoldState = sheetController,
        sheetContent = { /* 自定义内容 */ },
        sheetDragHandle = {},
        sheetContainerColor = Color.Transparent,
        sheetShadowElevation = 0.dp,
        sheetSwipeEnabled = false
    ) {}
}

两种方法均能解决首次点击无法展开弹窗的问题,推荐方法2,它将状态修改和UI动作解耦,逻辑更清晰。

内容的提问来源于stack exchange,提问作者Muhammad Haroon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:13:09