You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android中如何实现支持触摸透传的部分屏幕透明Overlay(Draw Over Other Apps)

实现Android透明Overlay的触摸透传效果

嘿,这个需求完全可以实现!我之前做类似悬浮窗功能的时候刚好研究过这块,给你梳理下具体的实现思路和关键代码细节:

核心原理

Overlay的触摸事件拦截逻辑和普通View一致:当View返回true表示消费了事件,返回false则会把事件继续向下传递给底层的应用窗口。我们要做的就是让Overlay的View完全不消费触摸事件,同时配置窗口属性让它不抢占焦点。

具体实现步骤

1. 配置WindowManager的布局参数

创建Overlay时,必须给WindowManager.LayoutParams设置两个关键flag,确保Overlay不会拦截所有触摸:

val layoutParams = WindowManager.LayoutParams().apply {
    // 根据Android版本选择合适的窗口类型,API 26+推荐用TYPE_APPLICATION_OVERLAY
    type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
    } else {
        @Suppress("DEPRECATION")
        WindowManager.LayoutParams.TYPE_PHONE
    }
    // 关键:不拦截所有触摸,让底层窗口能接收非Overlay区域的触摸
    flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
    // 关键:让Overlay不获取焦点,避免影响底层应用的输入交互
    flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    // 设置窗口为透明格式
    format = PixelFormat.TRANSLUCENT
    // 自定义窗口的位置和大小,比如覆盖屏幕指定区域
    gravity = Gravity.TOP or Gravity.LEFT
    x = 0
    y = 0
    width = 500
    height = 500
}

2. 让Overlay View不消费触摸事件

不管你用的是自定义View还是系统View,只需要让它的触摸事件方法返回false,所有触摸操作就会自动透传给底层应用:

class TransparentOverlayView(context: Context) : View(context) {
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        // 返回false表示不消费事件,事件会继续向下传递给底层应用
        return false
    }
}

如果是用XML布局的View,也可以直接设置触摸监听返回false:

overlayView.setOnTouchListener { _, _ -> false }

3. 可选:局部区域透传/拦截

如果你的Overlay需要部分区域拦截触摸、部分区域透传,可以在onTouchEvent里根据触摸坐标做判断:

override fun onTouchEvent(event: MotionEvent?): Boolean {
    event ?: return false
    val x = event.x
    val y = event.y
    // 示例:左上角100x100的区域拦截触摸,其他区域透传
    return if (x < 100 && y < 100) {
        // 在这里处理拦截的逻辑,比如弹窗点击、功能触发
        true
    } else {
        // 其他区域返回false,透传给底层应用
        false
    }
}

注意事项

  • 确保已经申请了SYSTEM_ALERT_WINDOW权限(即你提到的Draw over other Apps权限),Android 6.0及以上需要用户手动在系统设置中开启。
  • Android 10及以上对Overlay的窗口类型和权限有更严格的限制,务必适配TYPE_APPLICATION_OVERLAY类型。
  • 把Overlay的背景设为完全透明(比如android:background="@android:color/transparent"),避免视觉上不必要的遮挡。

内容的提问来源于stack exchange,提问作者Renattele Renattele

火山引擎 最新活动