2

多亏了这个很好的答案:https ://stackoverflow.com/a/63595830/741795我们现在可以跟踪键盘何时在 Android 中显示...不幸的是,我发现了一些问题。

事实证明,对于 API 29 及更低版本,OnApplyWindowInsetsListener.onApplyWindowInsets仅调用了:

  • 当活动在清单中有“adjustResize”标志时
  • 仅适用于纵向模式。

对于 api 30+,一切都适用于纵向和横向,并且没有标志。

由于这些限制,对于 api 29- 我使用不同的方法(见下面的代码),使用OnGlobalLayoutListener.onGlobalLayout

// in activity onCreate():

val rootView = window.decorView.rootView
        if (isApi30()) {
            val isKeyBoardVisible = isKeyboardShownOlderApis(rootView)
            Log.d("KeyBoardVisibility", "initial keyboard state is: $isKeyBoardVisible for view: $rootView")
            ViewCompat.setOnApplyWindowInsetsListener(rootView, WindowInsetListener(isKeyBoardVisible))
        } else {
            rootView.viewTreeObserver.addOnGlobalLayoutListener(KeyBoardListener(rootView))
        }

然后是实际的听众:

//TODO: beware of leaks use weak reference
    private class KeyBoardListener(val rootView: View) : ViewTreeObserver.OnGlobalLayoutListener {
        var isKeyBoardVisible: Boolean = false

        init {
            isKeyBoardVisible = isKeyboardShownOlderApis(rootView)
            Log.d("KeyBoardVisibility", "initial keyboard state is: $isKeyBoardVisible for view: $rootView")
        }

        /**
         * Does not get called in api 21-29 landscape when keyboard is opened/closed
         */
        override fun onGlobalLayout() {
            Log.d("KeyBoardVisibility", "onGlobalLayout called: orientation: " + rootView.resources.configuration.orientation)
            val keyBoardVisible = isKeyboardShownOlderApis(rootView)
            if (keyBoardVisible != isKeyBoardVisible) {
                Log.i("KeyBoardVisibility", "Keyboard is now ${if (keyBoardVisible) "visible" else "hidden"}")
                isKeyBoardVisible = keyBoardVisible
            }
        }
    }

    /**
     * Works api 30, 31
     * Works api 25 in portrait with android:windowSoftInputMode="adjustResize"
     */
    private class WindowInsetListener(initialKeyboardVisibility: Boolean) : OnApplyWindowInsetsListener {
        var isKeyBoardVisible = initialKeyboardVisibility

        @SuppressLint("LongLogTag")
        override fun onApplyWindowInsets(v: View?, insets: WindowInsetsCompat?): WindowInsetsCompat? {
            val keyBoardVisible = insets?.isVisible(ime()) ?: false
            Log.d("KeyBoardVisibility", "onApplyWindowInsets called: $v with keyboardVisibility: $keyBoardVisible")
            if (keyBoardVisible != isKeyBoardVisible) {
                Log.i("KeyBoardVisibilityChanged", "Keyboard is now ${if (keyBoardVisible) "visible" else "hidden"}")
                isKeyBoardVisible = keyBoardVisible
            }
            insets?.let {
                v?.onApplyWindowInsets(insets.toWindowInsets())
            }
            return insets
        }
    }
}

private fun isKeyboardShownOlderApis(rootView: View?): Boolean {
    if (rootView == null) {
        return false
    }
    val insets = ViewCompat.getRootWindowInsets(rootView)
    if (insets == null) {
        Log.i("KeyBoardVisibility", "insets is null")
    }
    return insets?.isVisible(ime()) ?: false
}

private fun isApi30() = Build.VERSION.SDK_INT >= 30

问题:onGlobalLayout当键盘在横向模式下显示/隐藏时不调用,我在许多模拟器和手机上尝试过,它确实适用于平板电脑。

我找到了这个示例项目:https ://github.com/android/user-interface-samples/tree/master/WindowInsetsAnimation但在 API 21-29 中也不会调用这些方法,这对于动画来说很好,但是不是我的情况,所以那里一定有问题。我到处搜索,根本没有找到任何有关此的信息。

更多信息:这将是一个 SDK 代码,所以我不能指望用户在清单中设置任何标志或我正在使用的任何 fitSystemWindows 标志,androidx.core:core-ktx:1.5.0但 1.6.0 有同样的问题。

关于我可以尝试什么的任何想法?我怀疑窗口不同,因为键盘与editText一起占据了整个屏幕,但为什么它可以与新的APIS一起使用?

4

0 回答 0