软件键盘与 Jetpack Compose 视图的内容重叠

Software keyboard overlaps content of jetpack compose view

假设我有一些 activity 带有 jetpack-compose 内容

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ScrollableColumn(
                modifier = Modifier
                    .fillMaxSize()
                    .border(4.dp, Color.Red)
            ) {
                val (text, setText) = remember { mutableStateOf("") }

                TextField(
                    value = text,
                    onValueChange = setText,
                    label = {},
                    modifier = Modifier
                        .fillMaxWidth()
                )

                for (i in 0..100) {
                    Text("Item #$i")
                }
            }
        }
    }

}

如果我启动此 activity 并专注于 TextField,则会弹出一个软件键盘。

但是,界面不会对此做出反应。 ScrollableColumn 的底部边框 (.border(4.dp, Color.Red)) 以及第 100 个项目 (Text("Item #$i")) 将不可见。

换句话说,软键盘与内容重叠。

如何让 Jetpack Compose 尊重可见区域的变化(由于软件键盘)?

您可以使用标准 android 程序,但我不知道是否存在特定于 Compose 的方法。

如果您将 SoftInputMode 设置为 SOFT_INPUT_ADJUST_RESIZE,布局将在键盘更改时调整大小。

class YourActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        
        setContent { /* Composable Content */ }
    }
}

否则,您可以使用清单中的标志。浏览此处获取更多信息: Move layouts up when soft keyboard is shown?

您可以使用 Accompanist 的插入库 https://google.github.io/accompanist/insets

首先在您的可组合层次结构的根部使用 ProvideWindowInsets,大部分时间在您的应用程序主题下方撰写并设置 windowInsetsAnimationsEnabled

ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
// content  }

在 TextField 上使用 navigationBarsWithImePadding() 修饰符

OutlinedTextField(
// other params,
modifier = Modifier.navigationBarsWithImePadding() )

最后确保从 activity(在 onCreate).如果您希望软件键盘 on/off 设置动画,请在 AndroidManifests 中设置您的 activity 的 windowSoftInputMode adjustResize

<activity
  android:name=".MyActivity"
  android:windowSoftInputMode="adjustResize">

我想到了使用伴奏插入库的想法。

有人可能会感兴趣,因为我的方法不会修改 应用程序的内容。

我link我的post如下:

我遇到了同样的问题。

使用OnGlobalLayoutListener,它将观察实际的输入法矩形大小,并在软键盘完全可见时触发。

对我有效的解决方案:

val bringIntoViewRequester = remember { BringIntoViewRequester() }
val scope = rememberCoroutineScope()
val view = LocalView.current
DisposableEffect(view) {
    val listener = ViewTreeObserver.OnGlobalLayoutListener {
        scope.launch { bringIntoViewRequester.bringIntoView() }
    }
    view.viewTreeObserver.addOnGlobalLayoutListener(listener)
    onDispose { view.viewTreeObserver.removeOnGlobalLayoutListener(listener) }
}
TextField(
    modifier = Modifier.bringIntoViewRequester(bringIntoViewRequester),
    ...
)

Origin here

如果您希望 TextField 在出现键盘时向上滚动。 以下它对我有用。 你需要添加这些

class YourActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    
    window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    
    setContent { /* Composable Content */ }
}

并将此添加到您的 app/build。gradle

implementation "com.google.accompanist:accompanist-insets-ui:0.24.7-alpha"