Android 全屏透明悬浮窗:点击事件记录与穿透实现

本文将详细介绍如何在Android应用中创建一个全屏透明的悬浮窗,并记录用户点击事件的位置,同时实现点击事件穿透到下层界面,无论下层界面是否属于当前应用。

1. 权限申请

首先,需要在 AndroidManifest.xml 文件中添加以下权限,以允许创建系统级别的悬浮窗:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

2. 创建悬浮窗服务

创建一个名为 FloatingWindowService 的服务类,继承自 Service,并在 AndroidManifest.xml 文件中注册该服务:

<service android:name=".FloatingWindowService" />

3. 创建悬浮窗

FloatingWindowService 类中重写 onCreate() 方法,创建全屏透明悬浮窗:

@Override
public void onCreate() {
    super.onCreate();

    // 创建全屏透明悬浮窗
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            PixelFormat.TRANSLUCENT);
    params.gravity = Gravity.TOP | Gravity.LEFT;
    params.x = 0;
    params.y = 0;
    params.width = WindowManager.LayoutParams.MATCH_PARENT;
    params.height = WindowManager.LayoutParams.MATCH_PARENT;

    View floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window_layout, null);
    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    windowManager.addView(floatingView, params);
}

4. 悬浮窗布局

res 目录下创建一个名为 floating_window_layout.xml 的布局文件,用于定义悬浮窗的界面布局。可以设置为全屏透明,以便不遮挡下层界面。

5. 记录点击事件位置

FloatingWindowService 类中为悬浮窗的根布局设置点击事件监听器,并记录点击的位置:

View floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window_layout, null);
floatingView.setOnTouchListener(new View.OnTouchListener() {
    private float initialX;
    private float initialY;
    private int initialTouchX;
    private int initialTouchY;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                initialX = params.x;
                initialY = params.y;
                initialTouchX = (int) event.getRawX();
                initialTouchY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                params.x = initialX + (int) (event.getRawX() - initialTouchX);
                params.y = initialY + (int) (event.getRawY() - initialTouchY);
                windowManager.updateViewLayout(floatingView, params);
                break;
            case MotionEvent.ACTION_UP:
                // 处理点击事件
                int clickX = (int) (event.getRawX() - initialTouchX);
                int clickY = (int) (event.getRawY() - initialTouchY);
                // TODO: 处理点击事件,包括点击位置记录和点击事件的穿透处理
                break;
        }
        return true;
    }
});

6. 点击事件穿透

点击事件穿透的实现需要根据具体需求进行自定义。以下是一些常见的方案:

  • 使用 FLAG_NOT_FOCUSABLE 标志: 将悬浮窗的 LayoutParams 设置为 FLAG_NOT_FOCUSABLE,使悬浮窗不获得焦点,从而允许点击事件穿透到下层界面。
  • 使用 View.setOnClickListener: 在悬浮窗的根布局中设置点击监听器,并在监听器中判断点击位置是否在需要穿透的区域。如果是,则将点击事件传递到下层界面。
  • 使用 AccessibilityService: 通过 AccessibilityService 可以获取下层界面的点击事件,并根据需要进行处理。

7. 移除悬浮窗

FloatingWindowService 类中重写 onDestroy() 方法,用于移除悬浮窗:

@Override
public void onDestroy() {
    super.onDestroy();
    if (floatingView != null) {
        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        windowManager.removeView(floatingView);
    }
}

总结

通过以上步骤,你可以创建一个全屏透明的悬浮窗,并记录用户点击事件的位置。点击事件的穿透处理需要根据具体需求进行自定义,选择合适的方案实现。

注意:

  • 在 Android 6.0 及更高版本上,需要在应用设置中手动开启 “悬浮窗权限”。
  • 点击事件穿透的实现可能存在兼容性问题,需要在不同设备上进行测试。
  • 使用悬浮窗时要注意避免过度使用,以免影响用户体验。

希望这篇文章能帮助你实现 Android 全屏透明悬浮窗的功能。

Android 全屏透明悬浮窗:点击事件记录与穿透实现

原文地址: https://www.cveoy.top/t/topic/qEy1 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录