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

Jetpack Compose中IME弹出时BottomSheetScaffold布局跳动问题求助

解决BottomSheetScaffold搭配TextField时布局跳动问题

问题描述

使用BottomSheetScaffold布局,搭配顶部导航栏与包含TextField的底部弹窗,点击弹窗内的TextField时,整个布局会出现严重跳动(疑似动画冲突),之后才调整到适配输入法的尺寸。已尝试以下操作但未解决:

  • 调整android:windowSoftInputMode为adjustPan/adjustResize等
  • 设置android:animateLayoutChanges="false"
  • 在不同布局层级应用imePadding(仅在NavHost上应用时内边距显示正常)

相关Modifier配置:

// 根Composable,NavHost的Modifier
Modifier.fillMaxSize().imePadding()

// 屏幕级Composable,BottomSheetScaffold的Modifier
Modifier.fillMaxSize()

// BottomSheetScaffold内部内容Column的Modifier
Modifier.padding(paddingValues).fillMaxSize()

解决方案

方案1:调整imePadding应用层级并禁用BottomSheet动画

核心是让BottomSheetScaffold直接响应输入法Insets,同时关闭BottomSheet的动画避免冲突:

@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        // 固定输入法调整模式为adjustResize
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
        setContent {
            var input by remember { mutableStateOf("") }
            val bottomSheetState = rememberBottomSheetState(
                initialValue = BottomSheetValue.PartiallyExpanded
            )
            ImeLayoutJumpShiftTheme {
                BottomSheetScaffold(
                    modifier = Modifier.fillMaxSize().imePadding(), // 将imePadding移到这里
                    topBar = { TopAppBar(title = { Text("Example") }) },
                    sheetPeekHeight = 125.dp,
                    sheetState = bottomSheetState,
                    // 禁用BottomSheet的动画,避免与输入法调整冲突
                    sheetAnimationSpec = null,
                    sheetContent = {
                        Column(modifier = Modifier.padding(16.dp)) {
                            TextField(value = input, onValueChange = { input = it })
                        }
                    }
                ) { paddingValues ->
                    LazyColumn(modifier = Modifier.padding(paddingValues)) {
                        items(12) {
                            ListItem(
                                headlineContent = { Text("Item $it") },
                                supportingContent = {
                                    Text("This is item #$it. It increases the amount of space this list item takes up to recreate the usage of list items in a real project.")
                                }
                            )
                        }
                    }
                }
            }
        }
    }
}

方案2:监听输入法状态主动控制BottomSheet

通过rememberImeState监听输入法显示/隐藏,主动调整BottomSheet的展开状态,避免被动布局调整导致的跳动:

@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
        setContent {
            var input by remember { mutableStateOf("") }
            val bottomSheetState = rememberBottomSheetState(
                initialValue = BottomSheetValue.PartiallyExpanded
            )
            val imeState = rememberImeState()
            val scope = rememberCoroutineScope()

            // 监听输入法状态,主动调整BottomSheet
            LaunchedEffect(imeState.isVisible) {
                if (imeState.isVisible) {
                    bottomSheetState.expand()
                } else {
                    bottomSheetState.partialExpand()
                }
            }

            ImeLayoutJumpShiftTheme {
                BottomSheetScaffold(
                    modifier = Modifier.fillMaxSize().imePadding(),
                    topBar = { TopAppBar(title = { Text("Example") }) },
                    sheetPeekHeight = 125.dp,
                    sheetState = bottomSheetState,
                    sheetContent = {
                        Column(modifier = Modifier.padding(16.dp)) {
                            TextField(value = input, onValueChange = { input = it })
                        }
                    }
                ) { paddingValues ->
                    LazyColumn(modifier = Modifier.padding(paddingValues)) {
                        items(12) {
                            ListItem(
                                headlineContent = { Text("Item $it") },
                                supportingContent = {
                                    Text("This is item #$it. It increases the amount of space this list item takes up to recreate the usage of list items in a real project.")
                                }
                            )
                        }
                    }
                }
            }
        }
    }
}

关键说明

  • imePadding需要直接应用在BottomSheetScaffold上,确保输入法Insets直接作用于整个脚手架布局,而非外层容器
  • 禁用BottomSheet动画(sheetAnimationSpec = null)可以避免输入法弹出时的动画冲突,彻底消除跳动
  • 主动监听输入法状态控制BottomSheet展开,能让布局调整更可控,适合需要保留BottomSheet动画的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:45:16