【问题标题】:Determine keyboard presence and change layout accordingly in Jetpack Compose在 Jetpack Compose 中确定键盘是否存在并相应更改布局
【发布时间】:2021-08-24 08:13:45
【问题描述】:

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

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

【问题讨论】:

    标签: android scroll android-jetpack-compose


    【解决方案1】:

    Since Compose 1.2.0-alpha03Accompanist Insets 大部分已移至 Compose Foundation,请查看 migration guide 了解更多信息细节。以下答案的主要变化是不再需要 ProvideWindowInsets 并且应该替换一些导入。


    您可以使用accompanist insets。您将能够使用LocalWindowInsets.current.ime.isVisible 或将.imePadding() 添加到屏幕容器中来检查是否显示了键盘。

    这很好用。但要使其正常工作,您必须禁用窗户装饰配件:

    此库不会禁用窗户装饰配件。为了让您的视图层次结构能够接收插图,您需要确保从您的 Activity 调用:WindowCompat.setDecorFitsSystemWindows(window, false)。您还需要将系统栏背景设置为透明,这可以通过我们的 System UI Controller 库来完成。

    如果您不想这样做,则必须寻找其他解决方案。


    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")
                    }
                }
            }
        }
    }
    


    附言这也对惰性视图没有帮助:它会减小容器大小,但不会滚动到所选项目。等待this issue解决

    【讨论】:

    • 惰性视图是指这不适用于 LazyColumn?
    • @Ali_Waris 是的,正如我所说的,这个修饰符会起作用——它会减小视图大小,但不会改变滚动位置,所以在视觉上不会有任何效果。必须等待撰写维护者做出一些解决方法。作为 tmp 解决方案,您可以尝试收听 LocalWindowInsets.current.ime.isVisible 并按索引滚动到项目。
    • LocalWindowInsets.current.ime.isVisible 即使听到这个,我是否必须禁用窗户装饰配件?
    • @Ali_Waris 是的。
    【解决方案2】:

    由于不推荐使用伴奏者的插图,因此应使用androidx.compose.foundation 处的插图。

    我可以使用WindowInsets.Companion.ime.getBottom(LocalDensity.current) &gt; 0 检查输入法是否显示。否则,如果更适合您的用例,也可以使用 Modifier.imePadding()。我不确定这是否适用于横向模式和其他奇怪的键盘组合,但它似乎适用于带有“底部”键盘的纵向模式。

    “官方”API 仍处于功能请求阶段,它在问题跟踪器上:https://issuetracker.google.com/issues/217770337

    【讨论】:

      猜你喜欢
      • 2023-02-09
      • 2021-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-22
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      相关资源
      最近更新 更多