【Android】创建一个可以在屏幕上拖动的悬浮窗

项目需求

在界面上创建一个悬浮窗,可以自由的移动这个悬浮窗

需求解决

1.添加权限

java 复制代码
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

2.请求权限

从 Android 6.0 (API 23) 开始,应用需要动态请求显示悬浮窗的权限。例如,可以在 MainActivity 中请求权限:

java 复制代码
public class MainActivity extends AppCompatActivity {

    private static final int OVERLAY_PERMISSION_REQUEST_CODE = 1234;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, OVERLAY_PERMISSION_REQUEST_CODE);
            } else {
                // 权限已经授予,启动悬浮窗服务
                startFloatingWindowService();
            }
        } else {
            // 系统版本低于6.0,不需要请求权限,直接启动悬浮窗服务
            startFloatingWindowService();
        }

    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == OVERLAY_PERMISSION_REQUEST_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (Settings.canDrawOverlays(this)) {
                    // 权限授予,启动悬浮窗服务
                    startFloatingWindowService();
                } else {
                    // 权限未授予,提示用户
                    // TODO: 处理权限未授予情况
                }
            }
        }
    }


    private void startFloatingWindowService() {
        Intent intent = new Intent(MainActivity.this, FloatingWindowService.class);
        startService(intent);
    }
}
  1. 创建悬浮窗服务
    实现一个服务(FloatingWindowService),它将负责创建和管理悬浮窗视图。
java 复制代码
public class FloatingWindowService extends Service {


    private WindowManager windowManager;
    private View floatingView;

    public FloatingWindowService() {
    }


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

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

        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

        floatingView = inflater.inflate(R.layout.floating_window, null);

        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        // 初始位置
        params.x = 0;
        params.y = 0;

        windowManager.addView(floatingView, params);

        // 使悬浮窗可拖动
        floatingView.setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;

            @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_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);
    }
}
  1. 创建悬浮窗布局
    在 res/layout 目录下创建一个名为 floating_window.xml 的布局文件:
java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#80000000"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="CSDN -> 我又来搬代码了"
        android:textColor="#FFFFFF" />

</LinearLayout>

注意:要记得在注册清单文件注册服务

java 复制代码
        <service
            android:name=".service.FloatingWindowService"
            android:enabled="true"
            android:exported="true" />

实现效果

这个可以随意拖动。

相关推荐
丘狸尾1 小时前
[cisco 模拟器] ftp服务器配置
android·运维·服务器
van叶~3 小时前
探索未来编程:仓颉语言的优雅设计与无限可能
android·java·数据库·仓颉
Crossoads7 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
li_liuliu8 小时前
Android4.4 在系统中添加自己的System Service
android
C4rpeDime10 小时前
自建MD5解密平台-续
android
鲤籽鲲12 小时前
C# Random 随机数 全面解析
android·java·c#
m0_5485147716 小时前
2024.12.10——攻防世界Web_php_include
android·前端·php
凤邪摩羯16 小时前
Android-性能优化-03-启动优化-启动耗时
android
凤邪摩羯16 小时前
Android-性能优化-02-内存优化-LeakCanary原理解析
android
喀什酱豆腐17 小时前
Handle
android