Android 無障礙全局懸浮窗實現(xiàn)示例
Android 無障礙的全局懸浮窗可以在屏幕上添加 UI 供用戶進(jìn)行快捷操作,可以展示在所有應(yīng)用程序之上長期展示。另一方面,在一些自動化場景下,可以用來屏蔽用戶行為,防止用戶手動操作打斷自動化流程。
無障礙添加 UI
無障礙服務(wù)添加 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 // 因為此權(quán)限才能展示處理 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 創(chuàng)建 View val rootView = LayoutInflater.from(service).inflate(R.layout.float_layer, null) wm?.addView(rootView, lp) }
然后在自定義的無障礙服務(wù)中去調(diào)用這個方法:
class MyAccessibilityService: AccessibilityService() { override fun onServiceConnected() { super.onServiceConnected() initView() } // ... }
需要注意的是,這里不能將 initView
添加到 onCreate
生命周期中,官方文檔也有一些放在 onCreate 中的操作,但實際上都會導(dǎo)致 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?
無障礙服務(wù)所有的初始化工作,都要放在 onServiceConnected
中執(zhí)行。這樣就可以將自定義的 UI 展示到屏幕上了。
關(guān)于無障礙服務(wù)的配置,可以參考官方 API 。
配置分析
從使用上來看,無障礙蒙層是通過 WindowManager 添加到屏幕上的。而關(guān)鍵的一些信息在 WindowManager.LayoutParams 配置的數(shù)據(jù)中。
Type
Window 有一個關(guān)鍵的屬性 type ,它被定義在 WindowManager 的內(nèi)部類 LayoutParams 中,它可以控制 Window 的顯示次序。主要分為三種:
- Application Window:應(yīng)用程序窗口 1-99 ,應(yīng)用程序窗口一般位于最底層。
- System Window:系統(tǒng)窗口 2000-2999 ,系統(tǒng)級窗口一般位于最頂層,不會被其他的window遮住。
- Sub Window:子窗口 1000-1999,子窗口一般是顯示在應(yīng)用窗口之上。
從三種窗口的值也可推斷出,type 的值越大,Window 就越靠近用戶。
在上面的使用中,我們將 type 設(shè)置為 TYPE_ACCESSIBILITY_OVERLAY
,它的值是 2032 ,是一個系統(tǒng)窗口,所以可以展示在應(yīng)用程序之上。 TYPE_ACCESSIBILITY_OVERLAY
,是無障礙服務(wù)用來展示 UI 專用的 窗口類型 。使用它可以在所有的應(yīng)用程序上展示蒙層。
Flag
flag 中包含了兩個關(guān)鍵的值 FLAG_NOT_TOUCHABLE
和 FLAG_NOT_FOCUSABLE
,和一些其他的 flag 。配置這兩個內(nèi)容,蒙層將不會影響任何用戶操作。
FLAG_NOT_TOUCHABLE
:可以將 Window 設(shè)置為永不接收觸摸事件,從而能夠?qū)⒂|摸事件透傳給蒙層遮蓋住的區(qū)域,不阻塞用戶操作。FLAG_NOT_FOCUSABLE
:可以將 Window 設(shè)置為永不獲取按鍵輸入焦點,用戶無法向這個 Window 發(fā)送按鍵或其他的按鈕時間,而被它覆蓋的內(nèi)容可以接收并響應(yīng)事件。FLAG_LAYOUT_NO_LIMITS
:允許窗口延伸到屏幕之外。FLAG_LAYOUT_IN_SCREEN
:將窗口放置在整個屏幕中,忽略來自父窗口的任何約束。
LayoutInDisplayCutoutMode
這個屬性可以用來控制 Window 在劉海屏的布局方式。
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
:僅當(dāng)劉海屏完全包含在系統(tǒng)欄中時,才允許窗口擴(kuò)展到劉海區(qū)域。 否則,窗口的布局使其不與劉海區(qū)域重疊。LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
:允許 Window 延伸到短的一側(cè)邊緣的劉海區(qū)域。LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
:Window 不允許延伸到劉海屏區(qū)域。LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
:允許 Window 延伸到所有的屏幕邊緣劉海區(qū)域。
到此這篇關(guān)于Android 無障礙全局懸浮窗實現(xiàn)示例的文章就介紹到這了,更多相關(guān)Android 無障礙全局懸浮窗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Flutter學(xué)習(xí)之矢量圖SVG的區(qū)域填色示例詳解
這篇文章主要為大家介紹了Flutter學(xué)習(xí)之矢量圖SVG的區(qū)域填色示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04Android編程使用AlarmManager設(shè)置鬧鐘的方法
這篇文章主要介紹了Android編程使用AlarmManager設(shè)置鬧鐘的方法,結(jié)合具體實例分析了Android基于AlarmManager實現(xiàn)鬧鐘功能的設(shè)置、取消、顯示等相關(guān)操作技巧,需要的朋友可以參考下2017-03-03Android清空編輯框內(nèi)容功能的實現(xiàn)實例代碼
本篇文章主要介紹了Android清空編輯框數(shù)據(jù)功能的實現(xiàn)實例代碼,非常具有實用價值,需要的朋友可以參考下。2017-03-03Android shape和selector 結(jié)合使用實例代碼
本篇文章主要介紹了Android shape和selector 的使用,這里提供了shape 和selector 的詳細(xì)介紹,并附有代碼實例,有興趣的朋友可以參考下2016-07-07android開發(fā)實現(xiàn)列表控件滾動位置精確保存和恢復(fù)的方法(推薦)
下面小編就為大家?guī)硪黄猘ndroid開發(fā)實現(xiàn)列表控件滾動位置精確保存和恢復(fù)的方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03Android使用post方式上傳圖片到服務(wù)器的方法
這篇文章主要介紹了Android使用post方式上傳圖片到服務(wù)器的方法,結(jié)合實例形式分析了Android文件傳輸?shù)南嚓P(guān)技巧,需要的朋友可以參考下2016-03-03