Android 無(wú)障礙全局懸浮窗實(shí)現(xiàn)示例
Android 無(wú)障礙的全局懸浮窗可以在屏幕上添加 UI 供用戶進(jìn)行快捷操作,可以展示在所有應(yīng)用程序之上長(zhǎng)期展示。另一方面,在一些自動(dòng)化場(chǎng)景下,可以用來(lái)屏蔽用戶行為,防止用戶手動(dòng)操作打斷自動(dòng)化流程。
無(wú)障礙添加 UI
無(wú)障礙服務(wù)添加 UI 十分簡(jiǎn)單,使用 LayoutInflater 在 AccessibilityService 的 onServiceConnected 添加一個(gè) UI:
// in AccessibilityService, service 代表 AccessibilityService 的子類實(shí)例
private fun initView() {
// 在屏幕頂部添加一個(gè) View
val wm = service.getSystemService(AccessibilityService.WINDOW_SERVICE) as? WindowManager
val lp = WindowManager.LayoutParams().apply {
type = TYPE_ACCESSIBILITY_OVERLAY // 因?yàn)榇藱?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 // 透?jìng)饔|摸事件
FLAG_NOT_FOCUSABLE or // 透?jìng)鬏斎胧录?
FLAG_LAYOUT_IN_SCREEN
width = MATCH_PARENT
height = MATCH_PARENT
}
// 通過(guò) LayoutInflater 創(chuàng)建 View
val rootView = LayoutInflater.from(service).inflate(R.layout.float_layer, null)
wm?.addView(rootView, lp)
}然后在自定義的無(wú)障礙服務(wù)中去調(diào)用這個(gè)方法:
class MyAccessibilityService: AccessibilityService() {
override fun onServiceConnected() {
super.onServiceConnected()
initView()
}
// ...
}需要注意的是,這里不能將 initView 添加到 onCreate 生命周期中,官方文檔也有一些放在 onCreate 中的操作,但實(shí)際上都會(huì)導(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ú)障礙服務(wù)所有的初始化工作,都要放在 onServiceConnected 中執(zhí)行。這樣就可以將自定義的 UI 展示到屏幕上了。
關(guān)于無(wú)障礙服務(wù)的配置,可以參考官方 API 。
配置分析
從使用上來(lái)看,無(wú)障礙蒙層是通過(guò) WindowManager 添加到屏幕上的。而關(guān)鍵的一些信息在 WindowManager.LayoutParams 配置的數(shù)據(jù)中。
Type
Window 有一個(gè)關(guān)鍵的屬性 type ,它被定義在 WindowManager 的內(nèi)部類 LayoutParams 中,它可以控制 Window 的顯示次序。主要分為三種:
- Application Window:應(yīng)用程序窗口 1-99 ,應(yīng)用程序窗口一般位于最底層。
- System Window:系統(tǒng)窗口 2000-2999 ,系統(tǒng)級(jí)窗口一般位于最頂層,不會(huì)被其他的window遮住。
- Sub Window:子窗口 1000-1999,子窗口一般是顯示在應(yīng)用窗口之上。
從三種窗口的值也可推斷出,type 的值越大,Window 就越靠近用戶。
在上面的使用中,我們將 type 設(shè)置為 TYPE_ACCESSIBILITY_OVERLAY ,它的值是 2032 ,是一個(gè)系統(tǒng)窗口,所以可以展示在應(yīng)用程序之上。 TYPE_ACCESSIBILITY_OVERLAY ,是無(wú)障礙服務(wù)用來(lái)展示 UI 專用的 窗口類型 。使用它可以在所有的應(yīng)用程序上展示蒙層。
Flag
flag 中包含了兩個(gè)關(guān)鍵的值 FLAG_NOT_TOUCHABLE 和 FLAG_NOT_FOCUSABLE ,和一些其他的 flag 。配置這兩個(gè)內(nèi)容,蒙層將不會(huì)影響任何用戶操作。
FLAG_NOT_TOUCHABLE:可以將 Window 設(shè)置為永不接收觸摸事件,從而能夠?qū)⒂|摸事件透?jìng)鹘o蒙層遮蓋住的區(qū)域,不阻塞用戶操作。FLAG_NOT_FOCUSABLE:可以將 Window 設(shè)置為永不獲取按鍵輸入焦點(diǎn),用戶無(wú)法向這個(gè) Window 發(fā)送按鍵或其他的按鈕時(shí)間,而被它覆蓋的內(nèi)容可以接收并響應(yīng)事件。FLAG_LAYOUT_NO_LIMITS:允許窗口延伸到屏幕之外。FLAG_LAYOUT_IN_SCREEN:將窗口放置在整個(gè)屏幕中,忽略來(lái)自父窗口的任何約束。
LayoutInDisplayCutoutMode
這個(gè)屬性可以用來(lái)控制 Window 在劉海屏的布局方式。
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:僅當(dāng)劉海屏完全包含在系統(tǒng)欄中時(shí),才允許窗口擴(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 無(wú)障礙全局懸浮窗實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Android 無(wú)障礙全局懸浮窗內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用Android實(shí)現(xiàn)跨頁(yè)面懸浮窗效果
- Android懸浮窗的實(shí)現(xiàn)步驟
- Android開(kāi)發(fā)懸浮窗踩坑解決
- Android實(shí)現(xiàn)懸浮窗效果
- Android應(yīng)用內(nèi)懸浮窗Activity的簡(jiǎn)單實(shí)現(xiàn)
- Android超簡(jiǎn)單懸浮窗使用教程
- Android實(shí)現(xiàn)懸浮窗的簡(jiǎn)單方法實(shí)例
- Android創(chuàng)建懸浮窗的完整步驟
- Android?懸浮窗開(kāi)發(fā)示例((動(dòng)態(tài)權(quán)限請(qǐng)求?|?前臺(tái)服務(wù)和通知?|?懸浮窗創(chuàng)建?)
相關(guān)文章
ProtoBuf動(dòng)態(tài)拆分Gradle?Module解析
這篇文章主要為大家介紹了ProtoBuf動(dòng)態(tài)拆分Gradle?Module解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
淺析Android手機(jī)衛(wèi)士手機(jī)定位的原理
手機(jī)定位的三種方式:網(wǎng)絡(luò)定位,基站定位,GPS定位。本文給大家介紹Android手機(jī)衛(wèi)士手機(jī)定位的原理,感興趣的朋友一起學(xué)習(xí)吧2016-04-04
Android應(yīng)用獲取設(shè)備序列號(hào)的方法
本篇文章主要介紹了Android應(yīng)用獲取設(shè)備序列號(hào)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
Android dataBinding與ListView及事件詳解
這篇文章主要介紹了Android dataBinding與ListView及事件詳解的相關(guān)資料,需要的朋友可以參考下2016-10-10
Android 按后退鍵退出Android程序的實(shí)現(xiàn)方法
本篇文章介紹了,在Android中按后退鍵退出Android程序的實(shí)現(xiàn)方法。需要的朋友參考下2013-04-04
Android實(shí)現(xiàn)外部喚起應(yīng)用跳轉(zhuǎn)指定頁(yè)面的方法
這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)外部喚起應(yīng)用跳轉(zhuǎn)指定頁(yè)面的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12
Kotlin中關(guān)于內(nèi)聯(lián)函數(shù)的一些理解分享
這篇文章主要給大家介紹了關(guān)于Kotlin中內(nèi)聯(lián)函數(shù)的一些理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
Android xml文件的序列化實(shí)現(xiàn)代碼
Android提供了XmlSerializer來(lái)實(shí)現(xiàn)XML文件的序列化。相比傳統(tǒng)方式,更高效安全,需要的朋友可以參考下2014-02-02
Android編程實(shí)現(xiàn)狀態(tài)保存的方法分析
這篇文章主要介紹了Android編程實(shí)現(xiàn)狀態(tài)保存的方法,結(jié)合實(shí)例形式分析了Android狀態(tài)保存的原理、實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-08-08

