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

Android Jetpack Compose Modal Bottom Sheet键盘弹出上移过度问题

Jetpack Compose Modal Bottom Sheet 键盘弹出后过度上移问题

问题现象

在Jetpack Compose中实现包含文本和输入框的简易Modal Bottom Sheet,正常显示无异常,但点击输入框弹出键盘后,底部弹窗被过度上移,底部边距相当于键盘高度的两倍。

相关代码

弹窗触发与显示代码

var showBottomSheet by remember { mutableStateOf(false) }

if (showBottomSheet) {
    ModalBottomSheet(
        onDismissRequest = { showBottomSheet = false },
        windowInsets = WindowInsets.ime,
        dragHandle = { BottomSheetDefaults.DragHandle() },
    ) {
        CollectionFormPage()
    }
}

弹窗内容代码

@Composable
fun CollectionFormPage(
  collectionFormViewModel: CollectionFormViewModel = hiltViewModel(),
) {

    val state = collectionFormViewModel.state.collectAsState()

    Surface(
        modifier = Modifier
            .padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
    ) {
        Column {
            Text(
                "Test", style = MaterialTheme.typography.titleMedium.copy(
                    color = MaterialTheme.colorScheme.onSurface
                )
            )
            TextField(
                modifier = Modifier.fillMaxWidth(),
                value = state.value.label,
                onValueChange = {
                    //TODO
                })
        }
    }
}

状态截图

  • 正常显示状态:Modal bottom sheet shown
  • 异常状态:Modal bottom sheet with huge bottom padding

解决方案

问题根源是**WindowInsets.ime的手动设置,与内容层的bottom = 16.dp padding叠加,加上ModalBottomSheet本身的自动IME适配逻辑,导致重复计算了键盘高度的偏移量**。

可以通过以下两种方式修复:

方式一:移除ModalBottomSheet的windowInsets参数

ModalBottomSheet默认已经内置了IME(输入法)的inset适配逻辑,无需手动指定WindowInsets.ime,移除该参数即可解决重复偏移问题:

ModalBottomSheet(
    onDismissRequest = { showBottomSheet = false },
    dragHandle = { BottomSheetDefaults.DragHandle() },
) {
    CollectionFormPage()
}

方式二:动态调整内容层的底部padding

如果需要保留自定义windowInsets设置,可以在内容层的padding中减去IME的底部inset值,避免重复偏移:

@Composable
fun CollectionFormPage(
  collectionFormViewModel: CollectionFormViewModel = hiltViewModel(),
) {
    val state = collectionFormViewModel.state.collectAsState()
    val imeBottomInset = WindowInsets.ime.getBottom(LocalDensity.current).toDp()
    
    Surface(
        modifier = Modifier
            .padding(
                start = 16.dp, 
                end = 16.dp, 
                bottom = max(16.dp - imeBottomInset, 0.dp)
            )
    ) {
        // 原有内容保持不变
    }
}

推荐使用方式一,因为ModalBottomSheet的默认适配逻辑已经能满足键盘弹出场景,手动指定WindowInsets.ime反而会打破原有适配逻辑,引发异常偏移。


内容的提问来源于stack exchange,提问作者Rares Cruceat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:06:17