Android悬浮窗的实现步骤

 更新时间:2024年01月30日 15:31:16   作者:Billy_Zuo  
最近想做一个悬浮窗秒表的功能,所以看下悬浮窗具体的实现步骤,接下来通过本文给大家介绍Android悬浮窗的实现,需要的朋友可以参考下

最近想做一个悬浮窗秒表的功能,所以看下悬浮窗具体的实现步骤

1、初识WindowManager

实现悬浮窗主要用到的是WindowManager

@SystemService(Context.WINDOW_SERVICE)
public interface WindowManager extends ViewManager {
	...
}

WindowManager是接口类,继承自接口ViewManager,可以通过获取WINDOW_SERVICE系统服务得到。而ViewManager接口有addView方法,我们就是通过这个方法将悬浮窗控件加入到屏幕中去。

2、设置权限

当API Level >= 23,显示悬浮窗功能,需要在清单文件AndroidManifest.xml中添加SYSTEM_ALERT_WINDOW权限,添加这个权限后才可以在其他应用上显示悬浮窗。

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

通过getSystemService方式获取WindowManager

val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager

3、LayoutParam设置

WindowManager的addView方法有两个参数,一个是需要加入的控件对象,另一个参数是WindowManager.LayoutParams对象。

// view – The view to be added to this window.
	// params – The LayoutParams to assign to view.
   public void addView(View view, ViewGroup.LayoutParams params);

其中LayoutParams的type变量,这个变量是用来指定窗口的类型。在设置这个变量时,需要对不同版本的Android系统进行适配。

        val layoutParams = WindowManager.LayoutParams()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE
        }

在Android 8.0之前,悬浮窗口设置可以为TYPE_PHONE,这种类型是用于提供用户交互操作的非应用窗口,现在这个类型已弃用了。
而Android 8.0对系统和API行为做了修改,包括使用SYSTEM_ALERT_WINDOW权限的应用无法再使用窗口类型来在其他应用和窗口上方显示提醒窗口:

  • TYPE_PHONE(已弃用)

  • TYPE_PRIORITY_PHONE

  • TYPE_SYSTEM_ALERT

  • TYPE_SYSTEM_OVERLAY

  • TYPE_SYSTEM_ERROR

如果需要实现在其他应用和窗口上方显示提醒窗口,那么必须该为TYPE_APPLICATION_OVERLAY的新类型。

4、检测是否允许开启悬浮窗

开启悬浮窗之前,还需要检测用户是否允许开启悬浮窗,通过系统提供的canDrawOverlays来检测

//检测是否允许开启悬浮窗
Settings.canDrawOverlays(context)

如果没有允许开启,需要跳转开启页面,让用户允许开启悬浮窗

startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))

5、FloatingService服务

悬浮窗一直显示在其他应用上层,需要新建FloatingService服务类,用于处理悬浮窗相关逻辑。

class FloatingService : Service() {
    override fun onCreate() {
        super.onCreate()
    }
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        showFloatingWindow();
        return super.onStartCommand(intent, flags, startId)
    }
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
    /**
     * 显示悬浮窗
     */
    private fun showFloatingWindow() {
        // 获取WindowManager服务
        val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        // 新建悬浮窗控件
        val button = Button(applicationContext)
        button.text = "Floating Window"
        button.setBackgroundColor(Color.BLUE)
        // 设置LayoutParam
        val layoutParams = WindowManager.LayoutParams()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE
        }
        layoutParams.format = PixelFormat.RGBA_8888
        layoutParams.flags =
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        layoutParams.width = ActionBar.LayoutParams.WRAP_CONTENT
        layoutParams.height = ActionBar.LayoutParams.WRAP_CONTENT
        layoutParams.x = 300
        layoutParams.y = 300
        // 将悬浮窗控件添加到WindowManager
        windowManager.addView(button, layoutParams);
    }
}

6、启动FloatingService

       viewBinding.btnFloating.setOnClickListener {
            if (Settings.canDrawOverlays(this)) {//检测是否具有悬浮窗权限
                startService(Intent(this,FloatingService::class.java))
            } else {
                startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
            }
        }

开启效果如下:

7、增加拖动功能

悬浮窗显示的位置可能会遮挡其他信息,这时就需要新增拖动功能,可以拖动到任何位置,实现的逻辑就是给布局View添加触摸事件,根据触摸和移动的位置来决定悬浮窗显示的位置。

        var x = 0
        var y = 0
        button.setOnTouchListener { view, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    x = event.rawX.toInt()
                    y = event.rawY.toInt()
                }
                MotionEvent.ACTION_MOVE -> {
                    val nowX = event.rawX.toInt()
                    val nowY = event.rawY.toInt()
                    val movedX = nowX - x
                    val movedY = nowY - y
                    x = nowX
                    y = nowY
                    layoutParams.x = layoutParams.x + movedX
                    layoutParams.y = layoutParams.y + movedY
                    // 更新悬浮窗控件布局
                    windowManager.updateViewLayout(view, layoutParams)
                }
                else -> {}
            }
            false
        }

到此这篇关于Android悬浮窗的实现的文章就介绍到这了,更多相关Android悬浮窗内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android进阶CameraX与Camera2使用比对详解

    Android进阶CameraX与Camera2使用比对详解

    这篇文章主要为大家介绍了Android进阶CameraX与Camera2使用比示例对详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Android自定义控件之自定义组合控件(三)

    Android自定义控件之自定义组合控件(三)

    这篇文章主要介绍了Android自定义控件之自定义组合控件,重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发成本,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Android  selector的实例详解

    Android selector的实例详解

    这篇文章主要介绍了Android selector的实例详解的相关资料,这里提供实例帮助大家理解掌握这部分知识,需要的朋友可以参考下
    2017-08-08
  • Android adb工具使用教程及安装问题

    Android adb工具使用教程及安装问题

    安卓调试桥是一种可以用来操作手机设备或模拟器的命令行工具,它是 Android 开发/测试人员不可替代的强大工具,它允许你与连接的Android设备进行通信,本文给大家介绍Android adb工具使用教程,感兴趣的朋友一起看看吧
    2025-04-04
  • Android编程之判断SD卡状态的方法

    Android编程之判断SD卡状态的方法

    这篇文章主要介绍了Android编程之判断SD卡状态的方法,结合实例分析了Android针对SD卡的权限操作及状态判定技巧,需要的朋友可以参考下
    2016-02-02
  • Android实现图片自动切换功能(实例代码详解)

    Android实现图片自动切换功能(实例代码详解)

    这篇文章主要介绍了Android实现图片自动切换功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • Android 监听屏幕是否锁屏的实例代码

    Android 监听屏幕是否锁屏的实例代码

    今天小编通过本文给大家分享android如何监听手机屏幕是否锁屏。实现方法很简单,需要的朋友参考下吧
    2017-09-09
  • uni-app Android离线打包的多环境配置方案

    uni-app Android离线打包的多环境配置方案

    本文介绍uni-app项目Android多环境打包方案,通过productFlavors区分包名和key、利用flavor覆盖资源和资产、规范变体命名和产物命名等方法,确保开发、测试、线上包稳定并行,发版更可控,需要的朋友可以参考下
    2026-04-04
  • Android自定义控件EditText实现清除和抖动功能

    Android自定义控件EditText实现清除和抖动功能

    这篇文章主要为大家详细介绍了Android自定义控件EditText实现清除和抖动功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • Android系统的五种数据存储形式实例(二)

    Android系统的五种数据存储形式实例(二)

    Android系统有五种数据存储形式,分别是文件存储、SP存储、数据库存储、contentprovider 内容提供者、网络存储。本文介绍了Android系统的五种数据存储形式,有兴趣的可以了解一下。
    2016-12-12

最新评论