Android 无障碍全局悬浮窗实现示例

目录
  • 无障碍添加 UI
  • 配置分析
    • Type
    • Flag
    • LayoutInDisplayCutoutMode

Android 无障碍的全局悬浮窗可以在屏幕上添加 UI 供用户进行快捷操作,可以展示在所有应用程序之上长期展示。另一方面,在一些自动化场景下,可以用来屏蔽用户行为,防止用户手动操作打断自动化流程。

无障碍添加 UI

无障碍服务添加 UI 十分简单,使用 LayoutInflater 在 AccessibilityService 的 onServiceConnected 添加一个 UI:

    // in AccessibilityService, service 代表 AccessibilityService 的子类实例
    private fun initView() {
        // 在屏幕顶部添加一个 View
        val wm = service.getSystemService(AccessibilityService.WINDOW_SERVICE) as? WindowManager
        val lp = WindowManager.LayoutParams().apply {
            type = TYPE_ACCESSIBILITY_OVERLAY // 因为此权限才能展示处理
          	layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
            format = PixelFormat.TRANSLUCENT
            flags = flags or
                    FLAG_LAYOUT_NO_LIMITS or
                    FLAG_NOT_TOUCHABLE or  // 透传触摸事件
                    FLAG_NOT_FOCUSABLE or  // 透传输入事件
                    FLAG_LAYOUT_IN_SCREEN
            width = MATCH_PARENT
            height = MATCH_PARENT
        }
        // 通过 LayoutInflater 创建 View
        val rootView = LayoutInflater.from(service).inflate(R.layout.float_layer, null)
        wm?.addView(rootView, lp)
    }

然后在自定义的无障碍服务中去调用这个方法:

class MyAccessibilityService: AccessibilityService() {
    override fun onServiceConnected() {
        super.onServiceConnected()
        initView()
    }
    // ...
}

需要注意的是,这里不能将 initView 添加到 onCreate 生命周期中,官方文档也有一些放在 onCreate 中的操作,但实际上都会导致 crash 。

java.lang.RuntimeException: Unable to create service com.chunyu.accessibilitydemo.service.AccessibilityDemoService: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

无障碍服务所有的初始化工作,都要放在 onServiceConnected 中执行。这样就可以将自定义的 UI 展示到屏幕上了。

关于无障碍服务的配置,可以参考官方 API 。

配置分析

从使用上来看,无障碍蒙层是通过 WindowManager 添加到屏幕上的。而关键的一些信息在 WindowManager.LayoutParams 配置的数据中。

Type

Window 有一个关键的属性 type ,它被定义在 WindowManager 的内部类 LayoutParams 中,它可以控制 Window 的显示次序。主要分为三种:

  • Application Window:应用程序窗口 1-99 ,应用程序窗口一般位于最底层。
  • System Window:系统窗口 2000-2999 ,系统级窗口一般位于最顶层,不会被其他的window遮住。
  • Sub Window:子窗口 1000-1999,子窗口一般是显示在应用窗口之上。

从三种窗口的值也可推断出,type 的值越大,Window 就越靠近用户。

在上面的使用中,我们将 type 设置为 TYPE_ACCESSIBILITY_OVERLAY ,它的值是 2032 ,是一个系统窗口,所以可以展示在应用程序之上。 TYPE_ACCESSIBILITY_OVERLAY ,是无障碍服务用来展示 UI 专用的 窗口类型 。使用它可以在所有的应用程序上展示蒙层。

Flag

flag 中包含了两个关键的值 FLAG_NOT_TOUCHABLEFLAG_NOT_FOCUSABLE ,和一些其他的 flag 。配置这两个内容,蒙层将不会影响任何用户操作。

  • FLAG_NOT_TOUCHABLE :可以将 Window 设置为永不接收触摸事件,从而能够将触摸事件透传给蒙层遮盖住的区域,不阻塞用户操作。
  • FLAG_NOT_FOCUSABLE :可以将 Window 设置为永不获取按键输入焦点,用户无法向这个 Window 发送按键或其他的按钮时间,而被它覆盖的内容可以接收并响应事件。
  • FLAG_LAYOUT_NO_LIMITS :允许窗口延伸到屏幕之外。
  • FLAG_LAYOUT_IN_SCREEN :将窗口放置在整个屏幕中,忽略来自父窗口的任何约束。

LayoutInDisplayCutoutMode

这个属性可以用来控制 Window 在刘海屏的布局方式。

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT :仅当刘海屏完全包含在系统栏中时,才允许窗口扩展到刘海区域。 否则,窗口的布局使其不与刘海区域重叠。
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES :允许 Window 延伸到短的一侧边缘的刘海区域。
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER :Window 不允许延伸到刘海屏区域。
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS :允许 Window 延伸到所有的屏幕边缘刘海区域。

到此这篇关于Android 无障碍全局悬浮窗实现示例的文章就介绍到这了,更多相关Android 无障碍全局悬浮窗内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 不依赖于Activity的Android全局悬浮窗的实现

    前言 当我们在手机上使用360安全卫士时,手机屏幕上时刻都会出现一个小浮动窗口,点击该浮动窗口可跳转到安全卫士的操作界面,而且该浮动窗口不受其他activity的覆盖影响仍然可见(多米音乐也有相关的和主界面交互的悬浮小窗口).那么这种不受Activity界面影响的悬浮窗口是怎么实现的呢? Android悬浮窗实现 实现基础 Android悬浮窗实现使用WindowManager WindowManager介绍 通过Context.getSystemService(Context.WINDOW_S

  • Android 8.0如何完美适配全局dialog悬浮窗弹出

    前言 最近项目targetSdkVersion升级到了26,出现很多问题趟了很多坑,其中就包括本篇的需要解决的问题:全局dialog 不显示. 出现场景 有时候我们需要在App中弹dialog,但是却不知道依附的是哪个Activity,这个时候通常会启动一个service来依附,显示一个全局的dialog. Android 6.0出现的悬浮窗权限 为什么从6.0说起? 在Android6.0之后,使用悬浮窗功能需要申请开启悬浮窗权限,在API23以下版本编译,悬浮窗权限关闭的,但是没有权限限制,

  • Android 无障碍全局悬浮窗实现示例

    目录 无障碍添加 UI 配置分析 Type Flag LayoutInDisplayCutoutMode Android 无障碍的全局悬浮窗可以在屏幕上添加 UI 供用户进行快捷操作,可以展示在所有应用程序之上长期展示.另一方面,在一些自动化场景下,可以用来屏蔽用户行为,防止用户手动操作打断自动化流程. 无障碍添加 UI 无障碍服务添加 UI 十分简单,使用 LayoutInflater 在 AccessibilityService 的 onServiceConnected 添加一个 UI: /

  • Android实现桌面悬浮窗、蒙板效果实例代码

    现在很多安全类的软件,比如360手机助手,百度手机助手等等,都有一个悬浮窗,可以飘浮在桌面上,方便用户使用一些常用的操作. 今天这篇文章,就是介绍如何实现桌面悬浮窗效果的. 首先,看一下效果图. 悬浮窗一共分为两个部分,一个是平常显示的小窗口,另外一个是点击小窗口显示出来的二级悬浮窗口. 首先,先看一下这个项目的目录结构. 最关键的就是红框内的四个类. 首先,FloatWindowService是一个后台的服务类,主要负责在后台不断的刷新桌面上的小悬浮窗口,否则会导致更换界面之后,悬浮窗口也会随

  • Android编程实现悬浮窗获取并显示当前内存使用量的方法

    本文实例讲述了Android编程实现悬浮窗获取并显示当前内存使用量的方法.分享给大家供大家参考,具体如下: 运行效果: 其中: 这一块就是悬浮窗,可以随意拖动,动态显示当前内存使用量. 下面看一下代码是如何实现的: 悬浮窗的实现是用了一个service,为什么要用service呢?了解service特点的大体就会明白.下面看一下: public class FloatService extends Service { WindowManager wm = null; WindowManager.

  • Android超简单悬浮窗使用教程

    完全自定义悬浮窗,保证100%学会的超简单悬浮窗 先看看效果图: 图1                                                 图2                                              图3 图1只需要31行代码即可完成. 我们来看看这些都是如何实现的 使用前需要依赖库: 第一步:将以下存储库将其添加到根构建中. allprojects { repositories { ... maven { url 'https:/

  • Android应用内悬浮窗Activity的简单实现

    目录 前言 缩放方法 悬浮样式 点击穿透空白 移动悬浮窗 例子的完整代码 styles.xml layout activity 运行效果 小结 前言 悬浮窗是一种比较常见的需求.例如把视频通话界面缩小成一个悬浮窗,然后用户可以在其他界面上处理事情. 本文给出一个简单的应用内悬浮窗实现.可缩小activity和还原大小.可悬浮在同一个app的其他activity上.使用TouchListener监听触摸事件,拖动悬浮窗. 缩放方法 缩放activity需要使用WindowManager.Layou

  • Android应用内悬浮窗的实现方案示例

    1.悬浮窗的基本介绍 悬浮窗,大家应该也不陌生,凌驾于应用之上的一个小弹窗,实现上很简单,就是添加一个系统级别的窗口,Android中通过WindowManagerService( WMS)来管理所有的窗口,对于WMS来说,管你是Activity.Toast.Dialog,都不过是通过WindowManagerGlobal.addView()添加的一个个View. Android中的窗口分为三个级别: 1.1 应用窗口,比如Activity的窗口; 1.2 子窗口,依赖于父窗口,比如PopupW

  • Android实现类似qq微信消息悬浮窗通知功能

    实现方法:(需要开启悬浮窗通知权限.允许应用在其他应用上显示) 一.利用headsup 悬挂式Notification,他是5.0中新增的,也就是API中的Headsup的Notification,可以在不打断用户操作的时候,给用户通知 二.使用Window创建悬浮窗 当window属性设置为FLAGE_NOT_FOCUSABLE表示不需要获取焦点,也不需要接受各种输入事件,此标记会同时启用FLAGE_NOT_TOUCH_MODEL,最终事件会直接传递给下层具有焦点的Widow FLAGE_NO

  • Android仿360桌面手机卫士悬浮窗效果

    大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我先说几句不相干的话. 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多高手喜欢把自己的经验写在网上,供大家来学习,我也是从中受惠了很多,在此我深表感谢.可是我发现我却从来没有将自己平时的一些心得拿出来与大家分享,共同学习,太没有奉献精神了.于是我痛定思痛,决定从今天开始写博客,希望可以指点在我后面的开发者,更快地进入Android开发者的行列当中. 好了,废话就说这么

  • Android 实现可任意拖动的悬浮窗功能(类似悬浮球)

    最近开发项目中,有个在屏幕上任意拖动的悬浮窗功能,其实就是利用 WindowManager的api来完成这个需求,具体的实现的功能如下: 1.自定义view import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.util.Log; import android.util.TypedValu

随机推荐