如何修复Compose Material3中ModalBottomSheet与键盘的空隙问题
问题:Material3 1.1.1中ModalBottomSheet与键盘间出现空隙
在使用androidx.compose.material3:material3:1.1.1版本时,给TextField设置焦点后,键盘弹出时ModalBottomSheet与键盘之间会出现空隙。尝试过修改ModalBottomSheet的WindowInsets,以及在其内容中添加Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))来修复,但都没有解决问题。最终通过实现一个类似Dialog的BottomSheet满足了需求,但ModalBottomSheet组件本身的问题仍未解决。

相关实现代码
RenameBottomSheet 实现
@OptIn(ExperimentalMaterial3Api::class) @Composable fun RenameBottomSheet( newPersonalizedName: MutableState<String>, showState: MutableState<Boolean>, onConfirmClick: () -> Unit ) { val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val suffix = "${newPersonalizedName.value.length}/30" DragHandleBottomSheet( bottomSheetState = bottomSheetState, showState = showState, dragHandle = { BottomSheetHeader( iconResId = R.drawable.ic_edit, titleResId = R.string.rename ) }) { Column( modifier = Modifier .background(Theme.colorScheme.bottomBarBackgroundColor) .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { InputTextField( modifier = Modifier.fillMaxWidth(), text = newPersonalizedName.value, onValueChange = { if (it.length <= 30) newPersonalizedName.value = it }, label = stringResource(id = R.string.rename_label), suffix = suffix ) Spacer(modifier = Modifier.size(28.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center ) { ButtonWithoutBorder( text = stringResource(id = R.string.cancel), modifier = Modifier.weight(1f), onClick = { showState.value = false } ) Spacer(modifier = Modifier.size(12.dp)) DefaultButton( modifier = Modifier.weight(1f), textResId = R.string.save, onClick = onConfirmClick ) } } } }
DragHandleBottomSheet 实现
@OptIn(ExperimentalMaterial3Api::class) @Composable fun DragHandleBottomSheet( bottomSheetState: SheetState, showState: MutableState<Boolean>, dragHandle: @Composable (() -> Unit), content: @Composable ColumnScope.() -> Unit, ) { if (showState.value) { ModalBottomSheet( modifier = Modifier.imePadding(), onDismissRequest = { showState.value = false }, sheetState = bottomSheetState, scrimColor = VtbTheme.colorScheme.scrim, containerColor = VtbTheme.colorScheme.background, shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp), tonalElevation = 0.dp, dragHandle = dragHandle, ) { content() Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars)) } } }
ButtonWithoutBorder 实现
@Composable fun ButtonWithoutBorder( modifier: Modifier = Modifier, text: String? = null, textResId: Int? = null, isEnabled: Boolean = true, onClick: () -> Unit = {} ) { val buttonText = if (textResId != null) stringResource(id = textResId) else text.orEmpty() val alpha = if (isEnabled) 1f else 0.4f Box( modifier = modifier .requiredHeight(44.dp) .alpha(alpha) .background( color = Theme.colorScheme.blueSecondary, shape = Theme.shapes.compact ) .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null, onClick = { onClick.invoke() } ), contentAlignment = Alignment.Center ) { Text( text = buttonText, style = Theme.typography.Regular_14.copy( color = Theme.colorScheme.secondaryButtonTextColorDefault ), ) } }
DefaultButton 实现
@Composable fun DefaultButton( modifier: Modifier = Modifier, text: String? = null, textResId: Int? = null, isSelected: MutableState<Boolean> = mutableStateOf(true), onClick: () -> Unit = {} ) { val buttonText = if (textResId != null) stringResource(id = textResId) else text.orEmpty() Box( modifier = modifier .padding(4.dp) .clickable { onClick.invoke() } .requiredHeight(44.dp) .border( BorderStroke(if (isSelected.value) 0.dp else 1.dp, buttonColor), RoundedCornerShape(10.dp) ) .background( if (isSelected.value) buttonColor else backgroundColor, RoundedCornerShape(10.dp) ), contentAlignment = Alignment.Center ) { Text( text = buttonText, fontSize = 14.sp, color = if (isSelected.value) Color.White else textColor ) } }
更新:替代方案
找到符合需求的实现方式,但未解决ModalBottomSheet组件本身的问题:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun DialogLikeBottomSheet( showState: MutableState<Boolean>, shape: Shape = BottomSheetDefaults.ExpandedShape, dragHandle: (@Composable () -> Unit)? = null, content: @Composable () -> Unit, ) { if (showState.value) { val transitionState = remember { MutableTransitionState(false).apply { targetState = true } } Dialog( onDismissRequest = { showState.value = false }, properties = DialogProperties(usePlatformDefaultWidth = false) ) { val dialogWindowProvider = LocalView.current.parent as DialogWindowProvider dialogWindowProvider.window.setGravity(Gravity.BOTTOM) AnimatedVisibility( visibleState = transitionState, enter = slideInVertically(initialOffsetY = { it }), exit = slideOutVertically(targetOffsetY = { it }) ) { Surface(shape = shape) { Column { if (dragHandle != null) dragHandle() content() } } } } } }
内容的提问来源于stack exchange,提问作者Игорь Иванов
相关产品推荐
相关产品推荐

