-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
onGlobalLayout 需要判定全屏以及导航栏开启状态,不然会产生误判 #5
Comments
谢谢,目前工作较忙,有空会优化这些bug |
请问全屏状态下键盘高度该如何获取呢 |
微信这个功能刚出来的时候,我也研究过它的键盘表情切换动画,这里我给出我的实现键盘高度计算的方法,目前没发现有兼容性问题 @FreddyChen class KeyboardChangeMonitor(
private val context: Context,
private val parentView: View
) : PopupWindow(context), ViewTreeObserver.OnGlobalLayoutListener {
private val isAtLeastSdkR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
class AssistPopupWindow(
context: Context,
private val parentView: View
) : PopupWindow(context) {
private val isAtLeastSdkR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
init {
if (!isAtLeastSdkR) {
contentView = Space(context)
softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
width = 0
height = WindowManager.LayoutParams.MATCH_PARENT
}
}
fun start() {
if (!isAtLeastSdkR) {
if (!isShowing && parentView.windowToken != null) {
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
}
}
}
fun getPopHeight(): Int {
return if (isAtLeastSdkR) 0 else contentView.height
}
}
var observer: ((Int, Int) -> Unit)? = null
private val assistPopupWindow by lazy(LazyThreadSafetyMode.NONE) {
AssistPopupWindow(context, parentView)
}
private var lastKeyboardHeight = 0
private var currentKeyboardHeight = 0
init {
if (!isAtLeastSdkR) {
contentView = Space(context).also {
it.viewTreeObserver.addOnGlobalLayoutListener(this)
}
softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE or
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
inputMethodMode = INPUT_METHOD_NEEDED
width = 0
height = WindowManager.LayoutParams.MATCH_PARENT
}
}
override fun onGlobalLayout() {
if (!isAtLeastSdkR) {
handleOnGlobalLayout()
}
}
fun isShowKeyboard() = currentKeyboardHeight > 120
fun lastIsShowKeyboard() = lastKeyboardHeight > 120
@SuppressLint("NewApi")
fun start() {
if (isAtLeastSdkR) {
(context as Activity).window.decorView.setOnApplyWindowInsetsListener { _, insets ->
insets.getInsets(WindowInsets.Type.navigationBars()).bottom.run {
handlerDispatchEvent(insets.getInsets(WindowInsets.Type.ime()).bottom.minus(this))
insets.inset(0, 0, 0, this)
}
}
} else {
if (!isShowing && parentView.windowToken != null) {
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
assistPopupWindow.start()
}
}
}
@SuppressLint("NewApi")
fun close() {
observer = null
if (isAtLeastSdkR) {
(context as Activity).window.decorView.setOnApplyWindowInsetsListener(null)
} else {
contentView.viewTreeObserver.removeOnGlobalLayoutListener(this)
dismiss()
assistPopupWindow.dismiss()
}
}
private fun handleOnGlobalLayout() {
val contentHeight = contentView.height
if (contentHeight <= 0) {
return // 忽略无需处理
}
val offset = assistPopupWindow.getPopHeight().minus(contentHeight)
val open = offset > context.dip(100f)
val newHeight = if (open) {
offset
} else {
0
}
handlerDispatchEvent(newHeight)
}
private fun handlerDispatchEvent(height: Int) {
val newHeight = height.coerceAtLeast(0)
if (currentKeyboardHeight == newHeight) {
return
}
lastKeyboardHeight = currentKeyboardHeight
val orientation = context.resources.configuration.orientation
if (newHeight < 120) {
currentKeyboardHeight = 0
notifyKeyboardHeightChanged(0, orientation)
} else {
currentKeyboardHeight = newHeight
notifyKeyboardHeightChanged(newHeight, orientation)
}
}
private fun notifyKeyboardHeightChanged(height: Int, orientation: Int) {
observer?.invoke(height, orientation)
}
} |
@Kuki93 大佬,看到你的微信切换表情面板,又看到你这个,方案没有特别大的问题,就是有些手机无法监听,同事的俩台手机就不行,型号华为Mate40系统鸿蒙2.0.0/型号红米Note9pro系统Android11 |
这个兼容性问题最后有解吗? |
使用PopupWindow辅助监听来将主视图设为adjustNothing,确实是个好方法。
onGlobalLayout 的判断经过我使用多种真机测试,发现需要做很多无效性判定。不然很容易产生误判。
1.横屏模式在切入后台,再切回前台,部分手机会产生视图旋转。触发布局调整。
2.底部导航栏状态变更会触发布局调整。
3.有些时候我们并不会把app设置为全屏,计算键盘高度并不总等于物理高减可视底。
4.有些机型点开软键盘后会频繁触发onGlobalLayout。
这个是我自己使用的一个,可以参考一下。
https://bitbucket.org/mm_longcheng/mm-core/src/dev/nwsi/proj/android/src/org/mm/nwsi/mmUIViewLayoutListener.java
The text was updated successfully, but these errors were encountered: