感谢这里的这个很好的答案:https://stackoverflow.com/a/63595830/741795 https://stackoverflow.com/a/63595830/741795我们现在可以跟踪 Android 中何时显示键盘...不幸的是我发现了一些问题。
事实证明,对于 API 29 及以下版本,OnApplyWindowInsetsListener.onApplyWindowInsets
只被称为:
- 当活动在清单中具有“调整调整大小”标志时
- 仅适用于纵向模式。
对于 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 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 一起使用?