1.使用ActivityExt.kt扩展获取键盘高度
/**ContentView*/
val Activity.mContentView: FrameLayout
get() {
return this.findViewById(android.R.id.content)
}
/**获取虚拟导航高度(部分手机可能不准)*/
fun Activity.getHeightNavigationBar(): Int {
return NavigationUtils.getNavigationBarHeight(this)
}
/**获取当前键盘高度(布局不填充到底部虚拟导航键)*/
fun Activity.getHeightKeyboard(): Int {
if (mContentView.height > 0) {
val rect = Rect()
window.decorView.getWindowVisibleDisplayFrame(rect)
val arr = intArrayOf(0, 0)
mContentView.getLocationOnScreen(arr)
return max(0, arr[1] + mContentView.height - rect.bottom)
} else {
val rect = Rect()
//使用最外层布局填充,进行测算计算
window.decorView.getWindowVisibleDisplayFrame(rect)
val heightDiff = window.decorView.height - rect.height()
val heightResult = heightDiff - mStatusBarHeight - getHeightNavigationBar()
//由于关闭键盘可能出现负数或者很小的值,所以直接判断为关闭键盘
return if (heightResult < 50) 0 else heightResult
}
}
/**添加键盘监听*/
fun Activity.addListerKeyboard(
naHeight: ((naHeight: Int) -> Unit)? = null,
keyboardHeight: ((keyboardHeight: Int) -> Unit)? = null
) {
val onGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
val realKeyboardHeight = getHeightKeyboard()
if (realKeyboardHeight != lastSetSetKeyboardHeight && window.decorView.height > 0
&& (realKeyboardHeight > 300 || realKeyboardHeight == 0)
) {
lastSetSetKeyboardHeight = realKeyboardHeight
disposable?.dispose()
disposable = Flowable.timer(100, TimeUnit.MILLISECONDS)
.onBackpressureLatest()
.compose(RxUtils.rx2SchedulerHelperF())
.subscribe {
val navigationHeight = NavigationUtils.getNavigationBarHeight(this)
if (navigationHeight != tempNavigationBarHeight) {
naHeight?.invoke(navigationHeight)
Log.i(TAG, "虚拟导航键高度=$naHeight")
tempNavigationBarHeight = navigationHeight
}
if (realKeyboardHeight != tempKeyboardHeight) {
keyboardHeight?.invoke(realKeyboardHeight)
Log.i(TAG, "键盘高度=$realKeyboardHeight")
tempKeyboardHeight = realKeyboardHeight
if (realKeyboardHeight > 100) {
saveKeyboardHeight = realKeyboardHeight
}
}
}
}
}
window.decorView.setTag(R.id.global_keyboard, onGlobalLayoutListener)
window.decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
2.全屏模式也可以监听键盘高度变化,需要自己处理view的移动(这样就能解决AndroidBug5497Workaround的bug了)
//全屏代码
val window = window
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
//manifet键盘方式
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
3.安卓5.0以上获取键盘高度,ContentView不移动,内容移动,需要自己处理Veiw的移动情况,需要adjustResize
//监听键盘高度
fun Activity.extKeyBoard(keyCall: (statusHeight: Int, navigationHeight: Int, keyBoardHeight: Int) -> Unit) {
mContentView.post { mContentView.layoutParams.height = mContentView.height }//防止键盘弹出导致整个布局高度变小
this.window.decorView.setOnApplyWindowInsetsListener(object : View.OnApplyWindowInsetsListener {
var preKeyOffset: Int = 0//键盘高度改变才回调
override fun onApplyWindowInsets(
v: View?,
insets: WindowInsets?
): WindowInsets {
insets?.let { ins ->
val navHeight = ins.systemWindowInsetBottom//下面弹窗到屏幕底部的高度,比如键盘弹出后的键盘+虚拟导航键高度
val offset = if (navHeight < ins.stableInsetBottom) navHeight
else navHeight - ins.stableInsetBottom
if (offset != preKeyOffset || offset == 0) {//高度变化
val decorHeight = mActivity.window.decorView.height//整个布局高度,包含虚拟导航键
if (decorHeight > 0) {//为了防止手机去设置页修改虚拟导航键高度,导致整个内容显示有问题,所以需要重新设置高度(与上面设置固定高度对应)
mContentView.layoutParams.height =
decorHeight - navHeight.coerceAtMost(ins.stableInsetBottom)//取小值
}
preKeyOffset = offset
keyCall.invoke(ins.stableInsetTop, ins.stableInsetBottom, offset)
}
}
return mActivity.window.decorView.onApplyWindowInsets(insets)
}
})
}
网友评论