安卓基础(悬浮窗)

悬浮窗

import android.app.Service;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;

public class FloatingWindowService extends Service {
    private WindowManager windowManager;
    private View floatingView;

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

        // 获取 WindowManager 对象
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        // 加载悬浮窗布局
        floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null);

        // 设置悬浮窗的布局参数
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                android.graphics.PixelFormat.TRANSLUCENT
        );

        // 设置悬浮窗的位置
        params.gravity = Gravity.TOP | Gravity.START;
        params.x = 0;
        params.y = 100;

        // 将悬浮窗添加到 WindowManager 中
        windowManager.addView(floatingView, params);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (floatingView != null) {
            // 移除悬浮窗
            windowManager.removeView(floatingView);
        }
    }

    @Override
    public IBinder onBind(android.content.Intent intent) {
        return null;
    }
}

参数说明

// 设置窗口的宽度,使其根据内部内容自动调整大小,能刚好包裹住内容
WindowManager.LayoutParams.WRAP_CONTENT, 
// 设置窗口的高度,同样使其根据内部内容自动调整大小,能刚好包裹住内容
WindowManager.LayoutParams.WRAP_CONTENT, 
// 指定窗口类型为应用覆盖层,可让窗口显示在其他应用之上(Android 8.0 及以上需特定权限)
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 
// 设置窗口的标志位,让窗口不获取焦点,触摸事件可穿透传递给下方窗口
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
// 设置窗口的像素格式为半透明,窗口会呈现半透明效果,可看到下方内容
android.graphics.PixelFormat.TRANSLUCENT 

窗口管理.布局参数 参数 = 窗口管理.布局参数

(实例)窗口管理.添加视图(加载xml布局,参数)

悬浮窗拖拽功能

import android.app.Service;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

public class FloatingWindowService extends Service {
    private WindowManager windowManager;
    private View floatingView;
    private WindowManager.LayoutParams params;
    private int initialX;
    private int initialY;
    private float initialTouchX;
    private float initialTouchY;

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

        // 获取 WindowManager 对象
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        // 加载悬浮窗布局
        floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null);

        // 设置悬浮窗的布局参数
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                android.graphics.PixelFormat.TRANSLUCENT
        );

        // 设置悬浮窗的位置
        params.gravity = Gravity.TOP | Gravity.START;
        params.x = 0;
        params.y = 100;

        // 将悬浮窗添加到 WindowManager 中
        windowManager.addView(floatingView, params);

        // 为悬浮窗设置触摸监听器以实现拖拽功能
        floatingView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // 记录初始位置和触摸点
                        initialX = params.x;
                        initialY = params.y;
                        initialTouchX = event.getRawX();
                        initialTouchY = event.getRawY();
                        return true;
                    case MotionEvent.ACTION_UP:
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        // 计算位置变化并更新悬浮窗位置
                        params.x = initialX + (int) (event.getRawX() - initialTouchX);
                        params.y = initialY + (int) (event.getRawY() - initialTouchY);
                        windowManager.updateViewLayout(floatingView, params);
                        return true;
                }
                return false;
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (floatingView != null) {
            // 移除悬浮窗
            windowManager.removeView(floatingView);
        }
    }

    @Override
    public IBinder onBind(android.content.Intent intent) {
        return null;
    }
}    

加载xml布局.设置触碰监听

MotionEvent event

event.getAction() //当前事件行动

MotionEvent.ACTION_DOWN

MotionEvent.ACTION_UP

MotionEvent.ACTION_MOVE

windowManager.updateViewLayout(floatingView, params); //悬浮窗更新


悬浮窗有两个按钮,一个是全截图,另一个是无障碍点击

floating_window.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="8dp">

    <Button
        android:id="@+id/full_screenshot_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="全截图" />

    <Button
        android:id="@+id/perform_accessibility_click_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="执行无障碍点击" />
</LinearLayout>    

FloatingWindowService.java

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

public class FloatingWindowService extends Service {
    private WindowManager windowManager;
    private View floatingView;
    private WindowManager.LayoutParams params;
    private int initialX;
    private int initialY;
    private float initialTouchX;
    private float initialTouchY;

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

        // 获取 WindowManager 对象
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        // 加载悬浮窗布局
        floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null);

        // 设置悬浮窗的布局参数
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                android.graphics.PixelFormat.TRANSLUCENT
        );

        // 设置悬浮窗的位置
        params.gravity = Gravity.TOP | Gravity.START;
        params.x = 0;
        params.y = 100;

        // 将悬浮窗添加到 WindowManager 中
        windowManager.addView(floatingView, params);

        // 为悬浮窗设置触摸监听器以实现拖拽功能
        floatingView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // 记录初始位置和触摸点
                        initialX = params.x;
                        initialY = params.y;
                        initialTouchX = event.getRawX();
                        initialTouchY = event.getRawY();
                        return true;
                    case MotionEvent.ACTION_UP:
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        // 计算位置变化并更新悬浮窗位置
                        params.x = initialX + (int) (event.getRawX() - initialTouchX);
                        params.y = initialY + (int) (event.getRawY() - initialTouchY);
                        windowManager.updateViewLayout(floatingView, params);
                        return true;
                }
                return false;
            }
        });

        // 找到两个按钮并设置点击监听器
        Button fullScreenshotButton = floatingView.findViewById(R.id.full_screenshot_button);
        Button performAccessibilityClickButton = floatingView.findViewById(R.id.perform_accessibility_click_button);

        fullScreenshotButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理全截图逻辑,这里只是示例,需要根据实际情况实现
                // 比如调用截图方法
                performFullScreenshot();
            }
        });

        performAccessibilityClickButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理执行无障碍点击逻辑,这里只是示例,需要根据实际情况实现
                // 比如调用无障碍点击方法
                performAccessibilityClick();
            }
        });
    }

    private void performFullScreenshot() {
        // 这里实现全截图的具体逻辑
        // 例如使用 MediaProjection 进行截图
        // 由于代码较为复杂,这里只是占位
        // 你可以参考 Android 官方文档或相关教程来实现
    }

    private void performAccessibilityClick() {
        // 这里实现执行无障碍点击的具体逻辑
        // 例如通过 AccessibilityService 来模拟点击操作
        // 由于代码较为复杂,这里只是占位
        // 你可以参考 Android 官方文档或相关教程来实现
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (floatingView != null) {
            // 移除悬浮窗
            windowManager.removeView(floatingView);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}    

从加载xml布局找到两个按钮

// 找到两个按钮并设置点击监听器
Button fullScreenshotButton = floatingView.findViewById(R.id.full_screenshot_button);
Button performAccessibilityClickButton = floatingView.findViewById(R.id.perform_accessibility_click_button);

两个按钮分别进行一个点击监听

fullScreenshotButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理全截图逻辑,这里只是示例,需要根据实际情况实现
                // 比如调用截图方法
                performFullScreenshot();
            }
        });

        performAccessibilityClickButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理执行无障碍点击逻辑,这里只是示例,需要根据实际情况实现
                // 比如调用无障碍点击方法
                performAccessibilityClick();
            }
        });
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奶龙牛牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值