当我单击 TextField 时,我需要向上滚动 UI 以向用户显示登录按钮,而不是将其隐藏在键盘后面。
我正在使用 RelocationRequester 来实现同样的目的。
我用它来检测键盘显示/隐藏事件:
fun listenKeyboard() {
val activityRootView =
(requireActivity().findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0)
activityRootView.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
private var wasOpened = false
private val DefaultKeyboardDP = 100
private val EstimatedKeyboardDP =
DefaultKeyboardDP + 48
private val r: Rect = Rect()
override fun onGlobalLayout() {
val estimatedKeyboardHeight = TypedValue
.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
EstimatedKeyboardDP.toFloat(),
activityRootView.resources.displayMetrics
)
.toInt()
activityRootView.getWindowVisibleDisplayFrame(r)
val heightDiff: Int = activityRootView.rootView.height - (r.bottom - r.top)
val isShown = heightDiff >= estimatedKeyboardHeight
if (isShown == wasOpened) {
return
}
wasOpened = isShown
keyboardVisibleState(isShown)
}
})
}
一旦键盘可见,我就会调用 relocationRequestor 的 BringIntoView()。
coroutineScope.launch {
delay(250)
relocationRequester.bringIntoView()
}
它的行为随机,在某些设备上工作,在其他设备上不工作。有没有更好的解决方案来解决这个问题?
自 Compose 1.2.0 起,Accompanist Insets 大部分移至 Compose Foundation 中,请查看 迁移指南 了解更多详细信息。以下答案的主要变化是不再需要
ProvideWindowInsets
,并且应该替换一些导入。
您可以使用伴奏插图。您可以使用
LocalWindowInsets.current.ime.isVisible
检查键盘是否显示,或将 .imePadding()
添加到屏幕容器中。
这个效果很好。但要使其正常工作,您必须禁用窗户装饰配件:
该库不会禁用窗户装饰配件。为了使您的视图层次结构能够接收插图,您需要确保从您的 Activity 中调用:WindowCompat.setDecorFitsSystemWindows(window, false)。您还需要将系统栏背景设置为透明,这可以使用我们的系统 UI 控制器库来完成。
如果您不想这样做,则必须寻找其他解决方案。
onCreate
中的示例:
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
ProvideWindowInsets {
ComposePlaygroundTheme {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.statusBarsPadding()
.navigationBarsWithImePadding()
.padding(10.dp)
) {
TextField(value = "", onValueChange = {})
Spacer(Modifier.weight(1f))
Button(onClick = {}) {
Text(text = "Proceed")
}
}
}
}
}
附注此外,这对惰性视图没有帮助:它会减小容器大小,但不会滚动到所选项目。等待这个问题解决
编辑 2024 年 7 月:
现在可以使用WindowInsets.isImeVisible
、imeAnimationSource
和imeAnimationTarget
。
请参阅下文 2022 年 3 月的答案。
由于伴奏者的插图已被弃用,因此应使用
androidx.compose.foundation
处的插图。
我可以使用
WindowInsets.Companion.ime.getBottom(LocalDensity.current) > 0
检查 IME 是否显示。否则,如果更适合您的用例,也可以使用 Modifier.imePadding()
。我不确定这是否适用于横向模式和其他奇怪的键盘组合,但它似乎可以在带有“底部”键盘的纵向模式下工作。
此的“官方”API 仍处于功能请求阶段,位于问题跟踪器上:https://issuetracker.google.com/issues/217770337
您也可以将以下行添加到活动部分的清单中:
android:windowSoftInputMode =“调整调整大小”
就像这个例子:
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.MyApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>