修复V2X弹窗异常
You must call removeView() on the child's parent first

Signed-off-by: donghongyu <donghongyu@zhidaoauto.com>
This commit is contained in:
donghongyu
2022-03-16 17:30:06 +08:00
parent e301c07bf9
commit 4a9b9b4066

View File

@@ -24,8 +24,8 @@ import com.mogo.eagle.core.utilcode.util.WindowUtils
* 弹窗Window 管理
*/
internal class WarningFloatWindowHelper(
val context: Context,
var config: WarningNotificationConfig
val context: Context,
var config: WarningNotificationConfig
) {
var TAG = "WarningFloatWindowHelper"
@@ -85,7 +85,7 @@ internal class WarningFloatWindowHelper(
frameLayout?.tag = config.floatTag
// 将浮窗布局文件添加到父容器frameLayout中并返回该浮窗文件
val floatingView = config.layoutView?.also { frameLayout?.addView(it) }
?: LayoutInflater.from(context).inflate(config.layoutId!!, frameLayout, true)
?: LayoutInflater.from(context).inflate(config.layoutId!!, frameLayout, true)
// 为了避免创建的时候闪一下我们先隐藏视图不能直接设置GONE否则定位会出现问题
floatingView.visibility = View.INVISIBLE
// 将frameLayout添加到系统windowManager中
@@ -142,34 +142,34 @@ internal class WarningFloatWindowHelper(
config.statusListenerMapIMoGo.forEach { listener ->
listener.onShow()
}
if (frameLayout == null|| frameLayout?.isAttachedToWindow == false || config.isAnim) return
if (frameLayout == null || frameLayout?.isAttachedToWindow == false || config.isAnim) return
enterAnimator = AnimatorManager(frameLayout!!, params, windowManager, config)
.enterAnim()?.apply {
// 可以延伸到屏幕外,动画结束按需去除该属性,不然旋转屏幕可能置于屏幕外部
params.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
.enterAnim()?.apply {
// 可以延伸到屏幕外,动画结束按需去除该属性,不然旋转屏幕可能置于屏幕外部
params.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
addListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {}
addListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {}
override fun onAnimationEnd(animation: Animator?) {
config.isAnim = false
if (!config.immersionStatusBar) {
// 不需要延伸到屏幕外了,防止屏幕旋转的时候,浮窗处于屏幕外
params.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
override fun onAnimationEnd(animation: Animator?) {
config.isAnim = false
if (!config.immersionStatusBar) {
// 不需要延伸到屏幕外了,防止屏幕旋转的时候,浮窗处于屏幕外
params.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
}
}
}
override fun onAnimationCancel(animation: Animator?) {}
override fun onAnimationCancel(animation: Animator?) {}
override fun onAnimationStart(animation: Animator?) {
floatingView.visibility = View.VISIBLE
config.isAnim = true
}
})
start()
}
override fun onAnimationStart(animation: Animator?) {
floatingView.visibility = View.VISIBLE
config.isAnim = true
}
})
start()
}
if (enterAnimator == null) {
floatingView.visibility = View.VISIBLE
windowManager.updateViewLayout(floatingView, params)
@@ -183,16 +183,16 @@ internal class WarningFloatWindowHelper(
config.statusListenerMapIMoGo.forEach { listener ->
listener.onDismiss()
}
if (frameLayout == null|| frameLayout?.isAttachedToWindow == false || (config.isAnim && enterAnimator == null)) return
if (frameLayout == null || frameLayout?.isAttachedToWindow == false || (config.isAnim && enterAnimator == null)) return
enterAnimator?.cancel()
val animator: Animator? =
AnimatorManager(frameLayout!!, params, windowManager, config).exitAnim()
AnimatorManager(frameLayout!!, params, windowManager, config).exitAnim()
if (animator == null) remove() else {
// 二次判断,防止重复调用引发异常
if (config.isAnim) return
config.isAnim = true
params.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
animator.addListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {}
@@ -214,7 +214,14 @@ internal class WarningFloatWindowHelper(
config.isAnim = false
WarningFloatWindowManager.remove(config.floatTag)
// removeView是异步删除在Activity销毁的时候会导致窗口泄漏所以使用removeViewImmediate直接删除view
windowManager.run { if (force) removeViewImmediate(frameLayout) else removeView(frameLayout) }
windowManager.run {
frameLayout?.removeAllViews()
if (force) {
removeViewImmediate(frameLayout)
} else {
removeView(frameLayout)
}
}
} catch (e: Exception) {
CallerLogger.e("$M_HMI$TAG", "浮窗关闭出现异常:$e")
}
@@ -235,9 +242,9 @@ internal class WarningFloatWindowHelper(
view.getLocationOnScreen(location)
// 通过绝对高度和相对高度比较,判断包含顶部状态栏
val statusBarHeight =
if (location[1] > params.y) WindowUtils.getStatusBarHeight(view.context.applicationContext) else 0
if (location[1] > params.y) WindowUtils.getStatusBarHeight(view.context.applicationContext) else 0
val parentBottom =
WindowUtils.getScreenHeight(view.context.applicationContext) - statusBarHeight
WindowUtils.getScreenHeight(view.context.applicationContext) - statusBarHeight
when (config.gravity) {
// 右上
Gravity.END, Gravity.END or Gravity.TOP, Gravity.RIGHT, Gravity.RIGHT or Gravity.TOP ->