日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android?無障礙全局懸浮窗實現示例_Android

作者:自動化BUG制造器 ? 更新時間: 2022-08-06 編程語言

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 延伸到所有的屏幕邊緣劉海區域。

原文鏈接:https://juejin.cn/post/7108668826727743519

欄目分類
最近更新