多亏了这个很好的答案: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一起使用?