繁体   English   中英

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

[英]Software keyboard overlaps content of jetpack compose view

假设我有一些关于 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")
                }
            }
        }
    }

}

如果我要启动此活动并专注于 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 */ }
    }
}

否则,您可以使用清单中的标志。 有关更多信息,请参见此处: 显示软键盘时向上移动布局?

我遇到了同样的问题。

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

为我工作的解决方案:

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),
    ...
)

原产地在这里

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

大多数情况下,首先在可组合层次结构的根部使用ProvideWindowInsets在您的应用程序主题下方编写并设置windowInsetsAnimationsEnabled true

ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
// content  }

在 TextField 上使用navigationBarsWithImePadding()修饰符

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

最后确保从您的活动(在onCreate 内)调用WindowCompat.setDecorFitsSystemWindows(window, false )。 如果您希望软件键盘开/关设置动画,请在 AndroidManifests 中设置您的活动的windowSoftInputMode adjustResize

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

除了 Compose,现在不需要外部库。 在清单文件中的活动上设置android:windowSoftInputMode=adjustResize

例如

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

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

</manifest>

然后对于您希望 UI 做出反应的可组合项,您可以使用Modifier.imePadding()来对 IME 可见性做出反应

Box(Modifier.imePadding()) {
  // content
}

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

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

我在下面链接我的帖子:

(Compose UI) - 键盘 (IME) 与应用程序的内容重叠

如果您希望 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"

在我的情况下,只需将android:windowSoftInputMode="adjustResize"添加到活动中就足以解决问题。
这取决于您如何构建 UI。 如果您的屏幕的根是可垂直滚动的容器或 Box,则键盘调整大小可能会自动管理。

使用修饰符imePadding() 这将允许特定的组合在键盘弹出时自行调整。 这不需要您在活动上设置任何标志

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM