首页 > 解决方案 > 在 Jetpack Compose 中确定键盘是否存在并相应更改布局

问题描述

当我单击 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()
}

它的行为是随机的,在某些设备上工作而不在其他设备上工作。有没有更好的解决方案来处理这个问题?

标签: androidscrollandroid-jetpack-compose

解决方案


您可以使用伴奏插图。您将能够检查是否使用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")
                }
            }
        }
    }
}


ps 这也对惰性视图没有帮助:它会减小容器大小,但不会滚动到所选项目。等待这个问题得到解决


推荐阅读