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
相关产品推荐
相关产品推荐

