如何管理AnimatedVisibility可见状态,规避隐藏状态冗余渲染
自定义ModalBottomSheet实现动画后卸载与无冗余渲染
你的现有代码中,背景层始终处于渲染状态,且整个Modal容器没有随visible状态卸载,导致冗余渲染。要实现动画后卸载、避免冗余的需求,可以通过以下方式修改:
修改后代码实现
@Composable fun CustomModalBottomSheet( visible: Boolean, onDismiss: () -> Unit, content: @Composable () -> Unit ) { // 用父AnimatedVisibility控制整个Modal的挂载与卸载 AnimatedVisibility( visible = visible, enter = fadeIn(animationSpec = tween(200)) + slideInVertically( initialOffsetY = { it }, animationSpec = tween(200) ), exit = fadeOut(animationSpec = tween(200)) + slideOutVertically( targetOffsetY = { it }, animationSpec = tween(200) ) ) { Box(modifier = Modifier.fillMaxSize()) { // 背景遮罩层,点击可触发关闭逻辑 Box( modifier = Modifier .fillMaxSize() .background(Color.Black.copy(alpha = 0.45f)) .clickable { onDismiss() } ) // 底部Sheet内容容器 Box( modifier = Modifier .align(Alignment.BottomCenter) .fillMaxWidth() ) { content() } } } }
核心逻辑说明
- 完全卸载控制:将整个Modal(背景遮罩+Sheet内容)包裹在
AnimatedVisibility中,当visible切换为false时,会先执行配置的退出动画,动画完成后整个组件会从Compose树中彻底移除,完全避免隐藏状态下的冗余渲染。 - 动画协同效果:通过
+运算符组合fadeIn/fadeOut(背景遮罩动画)与slideInVertically/slideOutVertically(Sheet滑入滑出动画),让遮罩和Sheet的动画同步执行,保证交互流畅度。 - 常规交互适配:给背景遮罩添加
clickable回调,符合ModalBottomSheet点击外部关闭的通用交互逻辑(可根据需求移除或修改)。
使用示例
var sheetVisible by remember { mutableStateOf(false) } Button(onClick = { sheetVisible = true }) { Text("打开BottomSheet") } CustomModalBottomSheet( visible = sheetVisible, onDismiss = { sheetVisible = false } ) { // 自定义Sheet内容 Column( modifier = Modifier .background(Color.White) .padding(16.dp) .fillMaxWidth() ) { Text("自定义BottomSheet内容") // 可添加更多组件... } }
内容的提问来源于stack exchange,提问作者Stanisław Olszak
相关产品推荐
相关产品推荐

