Android 浮窗开发之窗口层级
很多人都知道如何去實現(xiàn)一個簡單的浮窗,但是卻很少有人去深入的研究背后的流程機制,由于項目中浮窗交互比較復(fù)雜,遇到了些坑查看了很多資料,故總結(jié)浮窗涉及到的知識點:
窗口層級關(guān)系(浮窗是如何“浮”的)?
浮窗有哪些限制,如何越過用戶授權(quán)實現(xiàn)浮窗功能?
窗口與用戶輸入系統(tǒng)(Activity是如何接收到touch事件?)。
本章我們來研究第一個問題:浮窗為何會浮。 浮窗之所以叫浮窗,是因為它能懸浮于應(yīng)用或者桌面窗口之上,能脫離Activity而存在。為了研究其中區(qū)別,我們先來看看我們最熟悉的Activity是怎么顯示出來的。
Activity是怎么顯示出來的?
要弄清這個問題答案,我們先從Activity的setContentView()這個方法的源碼開始找起,在Activity中看到setCententView的源碼:
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
getWindow是返回返回Activity的mWindow變量,指向一個Window的對象,Window是一個抽象類,這里返回的是PhoneWindow對象(PhoneWindow是Window的子類),PhoneWindow中有一個DecorView對象,decorView成員,這是一個FrameLayout,setContentView的子布局最終會添加到decorView中,這個decorView就是當前窗口的根視圖,這個根視圖是如何最終被繪制出來的?在ActivityThread中有這樣一段代碼:
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
這個decorView,最終會被WindowManager.addView添加到繪制系統(tǒng)中,并類型是WindowManager.LayoutParams.TYPE_BASE_APPLICATION,這個參數(shù)決定了要繪制的窗口的z軸層次,為了避免思維棧過深,這里就不貼出詳細的源碼跟蹤過程了,直接給結(jié)論。
先來看看Activity和window的關(guān)系:
再來window和View的關(guān)系:
Activity窗口顯示過程:
說Activity是怎么顯示出來的,其實是說Activity管理的View是怎么顯示出來的。最后再來總結(jié)一下:
一、Activity通過setContentView設(shè)置的視圖是添加到PhoneWindow的根視圖decor中。
二、Window是一個抽象的概念,Window關(guān)了了一個View(根視圖),最終被WindowManager管理的還是一個View(根視圖)和它的LayoutParams,視圖繪制刷新都是通過WindowManager(WindowManagerGlobal)與WindowManagerServiceIPC交互調(diào)用底層繪制的。
三、Activity是四大組件中唯一和窗體緊密聯(lián)系的組件(這是為什么會有初學(xué)者把Activity直接理解為繪制界面的原因),所有掌管的視圖只不過是一種window和Dialog、Toast、墻紙所掌管的Window類型不一樣。
浮窗為什么會“浮”?
上面講到Activity的顯示過程其實已經(jīng)揭示了通用界面的顯示過程,浮窗的顯示過程更為簡單:
做過浮窗的同學(xué)應(yīng)該都明白了,為啥浮窗能脫離Activity而顯示,本質(zhì)上我們是把一個View交給WindowManager來管理了,LayoutParams.type類型決定了這個View顯示窗口的類型,不同類型顯示的窗口層次(z軸)是不一樣的。大方面來講可以分為應(yīng)用窗口(APPLICATION_WINDOW)、子窗口(SUB_WINDOW)、系統(tǒng)窗口(SYSTEM_WINDOW)三種類型,應(yīng)用窗口z軸范圍是1~99,子窗口的范圍是1001~1999,系統(tǒng)窗口是(2000~2999),所以要實現(xiàn)浮動窗口我們只能在系統(tǒng)窗口范圍中實現(xiàn)。
| 類型 | 常量范圍 | 子類 | 常量值 | 說明 | 例子 |
| APPLICATION_WINDOW | 1~99 | TYPE_BASE_APPLICATION | 1 | ||
| TYPE_APPLICATION | 2 | 應(yīng)用窗口 | 大部分的應(yīng)用程序窗口 | ||
| TYPE_APPLICATION_STARTING | 3 | 應(yīng)用程序的Activity顯示之前由系統(tǒng)顯示的窗口 | |||
| LAST_APPLICATION_WINDOW | 99 | ||||
| SUB_WINDOW | 1000~1999 | FIRST_SUB_WINDOW | 1000 | ||
| TYPE_APPLICATION_PANEL | 1000 | 顯示在母窗口之上,遮擋其下面的應(yīng)用窗口。 | |||
| TYPE_APPLICATION_MEDIA | 1001 | 顯示在母窗口之下,如果應(yīng)用窗口不挖洞,即不可見。 | SurfaceView,在小窗口顯示時設(shè)為MEDIA, 全屏顯示時設(shè)為PANEL | ||
| TYPE_APPLICATION_SUB_PANEL | 1002 | ||||
| TYPE_APPLICATION_ATTACHED_DIALOG | 1003 | ||||
| TYPE_APPLICATION_MEIDA_OVERLAY | 1004 | 用于兩個SurfaceView的合成,如果設(shè)為MEDIA,則上面的SurfaceView 擋住下面的SurfaceView | |||
| SYSTEM_WINDOW | 2000~2999 | TYPE_STATUS_BAR | 2000 | 頂部的狀態(tài)欄 | |
| TYPE_SEARCH_BAR | 2001 | 搜索窗口,系統(tǒng)中只能有一個搜索窗口 | |||
| TYPE_PHONE | 2002 | 電話窗口 | |||
| TYPE_SYSTEM_ALERT | 2003 | 警告窗口,在所有其他窗口之上顯示 | 電量不足提醒窗口 | ||
| TYPE_KEYGUARD | 2004 | 鎖屏界面 | |||
| TYPE_TOAST | 2005 | 短時的文字提醒小窗口 | |||
| TYPE_SYSTEM_OVERLAY | 2006 | 沒有焦點的浮動窗口 | |||
| TYPE_PRIORITY_PHONE | 2007 | 緊急電話窗口,可以顯示在屏保之上 | |||
| TYPE_SYSTEM_DIALOG | 2008 | 系統(tǒng)信息彈出窗口 | 比如SIM插上后彈出的運營商信息窗口 | ||
| TYPE_KEYGUARD_DIALOG | 2009 | 跟KeyGuard綁定的彈出對話框 | 鎖屏?xí)r的滑動解鎖窗口 | ||
| TYPE_SYSTEM_ERROR | 2010 | 系統(tǒng)錯誤提示窗口 | ANR 窗口 | ||
| TYPE_INPUT_METHOD | 2011 | 輸入法窗口,會擠占當前應(yīng)用的空間 | |||
| TYPE_INPUT_METHOD_DIALOG | 2012 | 彈出的輸入法窗口,不會擠占當前應(yīng)用窗口空間,在其之上顯示 | |||
| TYPE_WALLPAPER | 2013 | 墻紙 | |||
| TYPE_STATUS_BAR_PANEL | 2014 | 從狀態(tài)條下拉的窗口 | |||
| TYPE_SECURE_SYSTEM_OVERLAY | 2015 | 只有系統(tǒng)用戶可以創(chuàng)建的OVERLAY窗口 | |||
| TYPE_DRAG | 2016 | 浮動的可拖動窗口 | 360安全衛(wèi)士的浮動精靈 | ||
| TYPE_STATUS_BAR_PANEL | 2017 | ||||
| TYPE_POINTER | 2018 | 光標 | |||
| TYPE_NAVIGATION_BAR | 2019 | ||||
| TYPE_VOLUME_OVERLAY | 2020 | 音量調(diào)節(jié)窗口 | |||
| TYPE_BOOT_PROGRESS | 2021 | 啟動進度,在所有窗口之上 | |||
| TYPE_HIDDEN_NAV_CONSUMER | 2022 | 隱藏的導(dǎo)航欄 | |||
| TYPE_DREAM | 2023 | 屏保動畫 | |||
| TYPE_NAVIGATION_BAR_PANEL | 2024 | Navigation bar 彈出的窗口 | 比如說應(yīng)用收集欄 | ||
| TYPE_UNIVERSAL_BACKGROUND | 2025 | ||||
| TYPE_DISPLAY_OVERLAY | 2026 | 用于模擬第二顯示設(shè)備 | |||
| TYPE_MAGNIFICATION | 2027 | 用于放大局部 | |||
| TYPE_RECENTS_OVERLAY | 2028 | 當前應(yīng)用窗口,多用戶情況下只顯示在用戶節(jié)目 |
總結(jié)
以上是生活随笔為你收集整理的Android 浮窗开发之窗口层级的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SAP Commerce Acceler
- 下一篇: 抖音买米当卡是什么意思 抖音买米当卡含义