如何让ModalBottomSheet与键盘同步动画显示?
解决ModalBottomSheet与键盘同步弹出的卡顿问题
核心问题分析
你遇到的卡顿源于焦点请求时机与弹窗展开动画不同步:
- 过早请求焦点(如
LaunchedEffect(Unit))会导致弹窗动画和键盘动画并行执行,引发布局冲突; - 依赖
isAnimationRunning判断状态存在延迟,无法精准捕捉动画完成节点。
优化实现方案
通过精准等待弹窗展开完成后请求焦点,并配置布局适配键盘,实现同步流畅的效果:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun TimestampEditorSheet( timestamp: Timestamp, onDismiss: () -> Unit, onSave: (Timestamp) -> Unit, sheetState: SheetState, ) { val focusRequester = remember { FocusRequester() } LaunchedEffect(sheetState) { // 等待弹窗展开动画完全结束 sheetState.awaitExpand() // 立即请求输入框焦点,触发键盘同步弹出 focusRequester.requestFocus() } ModalBottomSheet( onDismissRequest = onDismiss, sheetState = sheetState, dragHandle = {}, // 让弹窗感知键盘高度,提前调整布局 windowInsets = WindowInsets.ime ) { TextField( state = textFieldState, placeholder = { Text("Description") }, modifier = Modifier .weight(1f) .focusRequester(focusRequester) .imePadding() // 确保输入框不被键盘遮挡,布局调整更平滑 ) } }
关键优化点
- 精准等待动画完成:使用
sheetState.awaitExpand()挂起函数替代isAnimationRunning判断,能精确捕获弹窗展开动画的结束时机,避免状态延迟问题。 - 布局适配键盘:
- 给
ModalBottomSheet设置windowInsets = WindowInsets.ime,让弹窗提前感知键盘高度变化,减少布局突然位移; - 给
TextField添加.imePadding(),确保输入框始终处于键盘上方,避免遮挡。
- 给
调用示例(父Composable)
val sheetState = rememberModalBottomSheetState() val scope = rememberCoroutineScope() Button(onClick = { scope.launch { sheetState.show() } }) { Text("打开编辑弹窗") } if (sheetState.isVisible) { TimestampEditorSheet( timestamp = Timestamp.now(), onDismiss = { scope.launch { sheetState.hide() } }, onSave = { /* 保存逻辑 */ }, sheetState = sheetState ) }
内容的提问来源于stack exchange,提问作者user32643450
相关产品推荐
相关产品推荐

