软件键盘覆盖了Jetpack Compose视图的内容。

54

假设我有一些带有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尊重可见区域的更改(由于软键盘)?

8个回答

37

除了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
}

你好, 在我的项目中,我必须处理以下两种情况:示例: 情况1:需要调整屏幕大小(AdjustResize) 情况2:不需要调整屏幕大小(AdjustResize)如果我们在清单文件和活动中设置了这些内容,我该如何处理这两种情况:注意:假设这两个是不同的组件和屏幕。 - Tippu Fisal Sheriff
我认为“true”不是这个字段(拼写错误)可能的值。 - Marty Miller
1
这是正确的答案,不需要任何第三方库...现在已经测试过了,imePadding很好地完成了工作。 - issamux
这意味着您可以忘记在每个可能显示键盘的屏幕中添加.imePadding()...因为使用android:windowSoftInputMode="adjustResize",系统不会自动将内容放置在键盘上方。 - user924
我认为它不会自动滚动内容以使文本字段可见 - undefined
显示剩余2条评论

35
你可以使用标准的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 */ }
    }
}

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


9
没问题,"android:windowSoftInputMode="adjustResize""(你提示的那个)起到了作用。非常感谢! - Nycta
3
我认为这只是在键盘弹出时设置了底部插入,但是除非“ScrollableColumn”将焦点项滚动到可见位置,否则内容仍然无法完全显示。 - Yu-Hsuan
4
谢谢,但在键盘输入法的下一个按钮点击后,文本框仍然不可见,即可滚动的列没有滚动,你有什么想法如何解决这个问题吗? - Hoby
将android:windowSoftInputMode="adjustResize"添加到Android清单文件中的Activity元素中效果最佳! - Stefan
7
SOFT_INPUT_ADJUST_RESIZE已经过时,有更新吗? - barryalan2633
显示剩余10条评论

23

你可以使用Accompanist的插图库 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) 。如果您想要打开/关闭软键盘时进行动画设置您的活动的 windowSoftInputModeadjustResize 在 AndroidManifests 中。

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

我只是按照答案中的说明,在Jetpack Compose的TextField中使用了ProvideWindowInsets(windowInsetsAnimationsEnabled = true),并且它对我起作用了。 - Dehan Wjiesekara
对我来说非常有效,第一个答案对我不够用,因为我想把文本字段下面的东西也移到键盘上方。 - Amin Keshavarzian
it's not for sroll layouts - jgnt32
如果在一个组合屏幕中我想要调整大小,而在另一个屏幕中不想要怎么办? - Cyph3rCod3r
2
已弃用。请参见https://dev59.com/L1IG5IYBdhLWcg3wkh4y#74036164。 - Adrián Prieto

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

3
imePadding() 还需要 .fillMaxHeight() - Bogdan Stolyarov

3
我遇到了相同的问题。
使用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),
    ...
)

点击此处查看来源


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

2

0
如果你想让你的文本框在键盘出现时向上滚动。 以下是我使用的方法。 你需要添加这些。
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"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接