android 悬浮窗全屏且部分区域可以透传触摸事件方案
·
改用全屏 Window,结合动态 TouchableRegion(Android 原生防拦截高级技巧)
如果你觉得频繁 updateViewLayout 在低端机上有性能负担,或者你的放大动画非常复杂(比如带有弹簧效果 SpringAnimation),你可以把 Window 设置为全屏,但通过系统底层接口限定它的“可触摸区域”。
Android 的 ViewTreeObserver 提了一个隐藏/高级 API:OnComputeInternalInsetsListener。它可以告诉系统:“虽然我这个 Window 是全屏的,但请只把下面这块矩形区域当成可以点击的,其他区域直接让事件穿透过去!”
实现代码:
解法 2:改用全屏 Window,结合动态 TouchableRegion(Android 原生防拦截高级技巧)
如果你觉得频繁 updateViewLayout 在低端机上有性能负担,或者你的放大动画非常复杂(比如带有弹簧效果 SpringAnimation),你可以把 Window 设置为全屏,但通过系统底层接口限定它的“可触摸区域”。
Android 的 ViewTreeObserver 提了一个隐藏/高级 API:OnComputeInternalInsetsListener。它可以告诉系统:“虽然我这个 Window 是全屏的,但请只把下面这块矩形区域当成可以点击的,其他区域直接让事件穿透过去!”
实现代码:
Kotlin
// 1. Window 参数依然设为全屏 + FLAG_NOT_TOUCH_MODAL
val layoutParams = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT
)
// 2. 在 View 挂载后,设置“可点击区域”监听
floatingView.viewTreeObserver.addOnComputeInternalInsetsListener { inoutInfo ->
// 告知系统:只响应可点击区域
inoutInfo.setTouchableInsets(
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION
)
// 3. 获取你的 RecyclerView (或者动画容器) 当前在屏幕上的实际可见范围
val rect = Rect()
recyclerView.getGlobalVisibleRect(rect)
// 4. 将该矩形区域设为唯一接收 Touch 事件的区域
inoutInfo.touchableRegion.set(rect)
}
更多推荐


所有评论(0)