SystemUI(二)WindowManager與LayoutParams的解析

在上一篇《# SystemUI(一)基于Android9.0SystemUI的啟動(dòng)與定制化
》中舶掖,了解了SystemUI的啟動(dòng)流程,同時(shí)也知道流程的最后主要是StatusBar通過(guò)WindowManager的addView()將view裝載在系統(tǒng)的界面上,在此之前都要利用WindowManager.LayoutParams來(lái)設(shè)置該window的顯示兵拢,那么在源碼里出現(xiàn)的WindowManager是什么?WindowManager.LayoutParams的參數(shù)又有什么特點(diǎn)逾礁?下文就將從這兩個(gè)方面來(lái)分析WindowManager说铃。

一、WindowManager是什么嘹履?

1.1 WindowManager與window的關(guān)系

WindowManager是什么腻扇?官方對(duì)于它的解釋只有這么一句話

The interface that apps use to talk to the window manager.

翻譯過(guò)來(lái)就是app與window通信的一個(gè)接口。從語(yǔ)義上看WindowManager是用來(lái)管理window的一個(gè)接口砾嫉,那么window又是什么幼苛?其實(shí)我們常見(jiàn)的Dialog、Popup焕刮、StatusBar等本質(zhì)就是window舶沿,window是一個(gè)抽象類,相當(dāng)于一個(gè)聯(lián)盟配并,Dialog括荡、Popup等view只有依附在window這個(gè)聯(lián)盟才能發(fā)揮功能,而WindowManager就像是聯(lián)盟的會(huì)長(zhǎng)溉旋,負(fù)責(zé)與子view等會(huì)員通信畸冲,并且能夠?qū)λ麄冞M(jìn)行增加、更新和刪除(WindowManager是一個(gè)接口观腊,具體的操作是在WindowManagerImpl實(shí)現(xiàn)類中)邑闲。

WindowManager繼承自ViewManager,ViewManager是用于向Activity添加和刪除子視圖的接口梧油,在官方文檔上顯示ViewManager中有三個(gè)抽象方法:

第一個(gè)addView():表示通過(guò)LayoutParams將參數(shù)傳遞給view监憎,然后將view添加到window上。也就是我們平常在系統(tǒng)界面上添加自定義Popup婶溯、Dialog鲸阔、菜單等。

第二個(gè)removeView():表示將window上的view刪除迄委。

第三個(gè)updateViewLayout():表示將view進(jìn)行更新褐筛。

1.2 WindowManager對(duì)象的獲取

當(dāng)我們想要在界面上添加一個(gè)子view就需要調(diào)用WindowManager的addView(),那么如何獲取WindowManager的實(shí)例呢叙身?文檔中給出了這樣一個(gè)方法:

可以知道方法中參數(shù)name的不同渔扎,將獲取不同的對(duì)象。name為WINDOW_SERVICE時(shí)信轿,即Context.getSystemService(Context.WINDOW_SERVICE) 返回WindowManager對(duì)象晃痴。除此之外以下列舉出比較常見(jiàn)的name所對(duì)應(yīng)的對(duì)象残吩。

name object
POWER_SERVICE PowerManager
ALARM_SERVICE AlarmManager
NOTIFICATION_SERVICE NotificationManager
ACTIVITY_SERVICE ActivityManager
LAYOUT_INFLATER_SERVICE LayoutInflater
LOCATION_SERVICE LocationManager
WIFI_SERVICE WifiManager
... ...

二、WindowManager.LayoutParams參數(shù)解析

2.1 構(gòu)造函數(shù)

在第一節(jié)里面提到過(guò)addView(View view, ViewGroup.LayoutParams params)是通過(guò)LayoutParams將參數(shù)傳遞給view倘核,然后將view添加到window上泣侮。LayoutParams表示包含了layout寬高,位置紧唱,類型等信息活尊,通過(guò)設(shè)置這些信息,生成不同的view漏益。

addView()中的第二個(gè)參數(shù)ViewGroup.LayoutParams是WindowManager.LayoutParams的父類蛹锰,我們具體來(lái)看看WindowManager.LayoutParams。

WindowManager.LayoutParams有下面7種構(gòu)造函數(shù):

Public constructors
1.WindowManager.LayoutParams()
2.WindowManager.LayoutParams(int _type)
3.WindowManager.LayoutParams(int _type, int _flags)
4.WindowManager.LayoutParams(int _type, int _flags, int _format)
5.WindowManager.LayoutParams(int w, int h, int _type, int _flags, int _format)
6.WindowManager.LayoutParams(int w, int h, int xpos, int ypos, int _type, int _flags, int _format)
7.WindowManager.LayoutParams(Parcel in)

對(duì)于具體的參數(shù)詳情在下面一一介紹绰疤。

2.2 Type

第二個(gè)構(gòu)造函數(shù)里包含了一個(gè)int 型的type铜犬,而type代表的是不同類型的window,window分為三種類型:

  • Application windows(應(yīng)用程序window)

    層級(jí)范圍為1-99轻庆,是屬于正常的頂級(jí)應(yīng)用程序window癣猾,例如我們所見(jiàn)到的Activity。

  • Sub-windows(子window)

    層級(jí)范圍為1000-1999榨了,例如部分Dialog煎谍。

  • System windows (系統(tǒng)window)

    層級(jí)范圍為2000-2999,是屬于最高層級(jí)龙屉,例如StatusBar呐粘,NavigationBar,覆蓋在所有window之上转捕。

而在這三種類型下又分為了很多不同的狀態(tài)作岖,官方文檔上介紹了多種type,這里就介紹幾種常見(jiàn)且重要的type五芝。

  • TYPE_APPLICATION_OVERLAY

    覆蓋于所有activity window之上痘儡,但低于關(guān)鍵系統(tǒng)window(如狀態(tài)欄,IME等)枢步,系統(tǒng)可以隨時(shí)改變這些窗口的位置沉删,大小或可見(jiàn)性,并且需要申請(qǐng)Manifest.permission.SYSTEM_ALERT_WINDOW權(quán)限醉途。

  • TYPE_STATUS_BAR

    表示狀態(tài)欄矾瑰,系統(tǒng)只有一個(gè)狀態(tài)欄窗口,它位于屏幕的頂部隘擎,所有其他窗口都向下移動(dòng)殴穴,當(dāng)我們想要替換成自己自定義的StatusBar時(shí),可設(shè)置type為它。

  • TYPE_SEARCH_BAR

    搜索欄采幌,系統(tǒng)只有一個(gè)搜索欄窗口并且位于屏幕頂部劲够。

  • TYPE_KEYGUARD_DIALOG

    鍵盤(pán)鎖顯示的對(duì)話框。

注意 :TYPE_TOAST休傍、TYPE_SYSTEM_OVERLAY征绎、TYPE_SYSTEM_ERROR、TYPE_SYSTEM_ALERT尊残、TYPE_PRIORITY_PHONE炒瘸、TYPE_PHONE這幾個(gè)type在API 26中已經(jīng)廢棄淤堵,由TYPE_APPLICATION_OVERLAY替代寝衫。

2.3 Flags

第三個(gè)構(gòu)造函數(shù)中參數(shù)多了一個(gè)int型的Flags,其表示window的屬性拐邪,下面就介紹幾種常見(jiàn)的Flag慰毅。

  • 默認(rèn)狀態(tài)不設(shè)置Flag
    在默認(rèn)不設(shè)置Flag的狀態(tài)下,在新window層級(jí)下的window將接受不到任何touch事件扎阶,即使是在新window的范圍外汹胃。

  • FLAG_NOT_FOCUSABLE
    表示此窗口范圍內(nèi)的事件自己處理,范圍外的事件依舊為原窗口處理东臀;例如點(diǎn)擊該窗口外的view着饥,依然會(huì)有響應(yīng)。另外只要設(shè)置了此Flag惰赋,都將會(huì)啟用FLAG_NOT_TOUCH_MODAL宰掉,最后,設(shè)置了該Flag就表示window不會(huì)與輸入方法交互赁濒,例如該window上有EditView轨奄,點(diǎn)擊EditView是不會(huì)彈出軟鍵盤(pán)的。

  • FLAG_NOT_TOUCH_MODAL
    表示即使window是處于上面的默認(rèn)狀態(tài)下拒炎,設(shè)置了該Flag挪拟,新window范圍外的view也是可以響應(yīng)touch事件。

  • FLAG_NOT_TOUCHABLE
    表示該window將不會(huì)接受任何touch事件击你,例如點(diǎn)擊該window玉组,不會(huì)有響應(yīng),只會(huì)傳給下面有聚焦的窗口丁侄。

  • FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS

    表示負(fù)責(zé)繪制系統(tǒng)欄背景惯雳。如果設(shè)置,系統(tǒng)欄將以透明背景繪制绒障,此窗口中的相應(yīng)區(qū)域?qū)⑻畛鋀indow#getStatusBarColor()和Window#getNavigationBarColor()中指定的顏色吨凑。

  • FLAG_FULLSCREEN

    表示顯示此window時(shí)隱藏所有屏幕裝飾(包括狀態(tài)欄)

  • FLAG_FORCE_NOT_FULLSCREEN

    表示比FLAG_FULLSCREEN低一級(jí),會(huì)顯示狀態(tài)欄

  • FLAG_SHOW_WALLPAPER

    表示要求系統(tǒng)壁紙顯示在該window后面,window表面必須是半透明的鸵钝,才能真正看到它背后的壁紙

  • FLAG_SHOW_WHEN_LOCKED

    表示window顯示在鎖屏的的界面上糙臼。此標(biāo)志在API27中已廢棄,使用R.attr.showWhenLocked或Activity.setShowWhenLocked(boolean)代替恩商。

2.4 Format

在第四個(gè)構(gòu)造函數(shù)中多了一個(gè)int型format參數(shù)变逃,這個(gè)參數(shù)則表示window所需的位圖格式,默認(rèn)為OPAQUE怠堪,也有可能是PixelFormat中的一種揽乱,另外setColorMode(int)的使用可能會(huì)覆蓋格式的選擇。

2.5 w粟矿、h

第五個(gè)構(gòu)造函數(shù)中多了兩個(gè)int型的w凰棉,h,w就是表示該window的width陌粹,h則是height撒犀,可以是具體數(shù)值,也可以是LayoutParams.MATCH_PARENT掏秩,LayoutParams.WRAP_CONTENT或舞。

2.6 xpos、ypos

在第六個(gè)構(gòu)造函數(shù)中多了兩個(gè)int型xpos和ypos蒙幻,其中xpos表示該window的橫坐標(biāo)位置映凳,ypos為縱坐標(biāo)位置。

也就是我們常見(jiàn)的 LayoutParams.x 和LayoutParams.y邮破。

2.7 Gravity

根據(jù)Gravity設(shè)置window在屏幕中的位置诈豌,例如Gravity.BOTTOM表示放置在容器的底部,Gravity.CENTER_HORIZONTAL表示放置在容器的水平中心决乎,Gravity.CENTER則表示放置在容器的中心队询,當(dāng)然還有其他的類型,可以根據(jù)自己的需求构诚,設(shè)置Gravity的位置蚌斩。

2.8 token

token是一個(gè)Binder代理對(duì)象,表示window的一個(gè)令牌范嘱,WMS會(huì)檢測(cè)傳入的token是否可以添加到系統(tǒng)上送膳,一般來(lái)說(shuō),系統(tǒng)會(huì)為我們自動(dòng)添加token丑蛤。

2.9 softInputMode

該屬性是表示設(shè)置window軟鍵盤(pán)輸入?yún)^(qū)域的顯示模式叠聋,例如我們有時(shí)候會(huì)發(fā)現(xiàn)window的軟鍵盤(pán)打開(kāi)會(huì)占據(jù)整個(gè)屏幕,遮擋了后面的視圖受裹,這時(shí)候就可以設(shè)置這個(gè)屬性碌补,調(diào)整軟鍵盤(pán)合適的樣式虏束。

例如以下幾種:

  • SOFT_INPUT_ADJUST_NOTHING

    將不會(huì)調(diào)整大小,直接覆蓋在window上厦章。

  • SOFT_INPUT_ADJUST_PAN

    具有輸入方法的window可以平移镇匀,例如有兩個(gè)EditView的輸入框,一個(gè)為Ev1袜啃,一個(gè)為Ev2汗侵,當(dāng)你點(diǎn)擊Ev1想要輸入數(shù)據(jù)時(shí),當(dāng)前的Ev1的輸入框會(huì)移到軟鍵盤(pán)上方群发,軟件盤(pán)是跟在Ev1的下面晰韵,保證Ev1是可見(jiàn)的,Ev2則不一定可見(jiàn)。

    另外該模式不能與SOFT_INPUT_ADJUST_RESIZE結(jié)合使用熟妓。

  • SOFT_INPUT_ADJUST_RESIZE

    整個(gè)window會(huì)平移調(diào)整大小雪猪,例如點(diǎn)擊一個(gè)EditView,整個(gè)layout都將平移可見(jiàn)且處于軟件盤(pán)的上方滑蚯。

    同樣的該模式不能與SOFT_INPUT_ADJUST_PAN結(jié)合使用浪蹂;另外如果窗口的布局參數(shù)標(biāo)志包含F(xiàn)LAG_FULLSCREEN抵栈,則將忽略這個(gè)值告材,窗口不會(huì)調(diào)整大小,但會(huì)保持全屏古劲。

  • SOFT_INPUT_ADJUST_UNSPECIFIED

    不指明斥赋,系統(tǒng)根據(jù)內(nèi)容自動(dòng)設(shè)置該模式和還是其他模式。

  • SOFT_INPUT_MASK_ADJUST

    window會(huì)調(diào)整大小以適應(yīng)軟鍵盤(pán)窗口产艾。

  • SOFT_INPUT_STATE_ALWAYS_HIDDEN

    當(dāng)此window獲得焦點(diǎn)時(shí)疤剑,始終隱藏任何軟輸入?yún)^(qū)域。

  • SOFT_INPUT_STATE_ALWAYS_VISIBLE

    當(dāng)此window獲得焦點(diǎn)時(shí)闷堡,始終顯示任何軟輸入?yún)^(qū)域隘膘。

三、總結(jié)

以上為WindowManager和LayoutParams 的介紹杠览,官方文檔中對(duì)于他們的介紹有點(diǎn)晦澀難懂弯菊,上面一部分就轉(zhuǎn)換為了日常說(shuō)法。在實(shí)際項(xiàng)目開(kāi)發(fā)中踱阿,我們有時(shí)候需要自定義一個(gè)window管钳,那么就要設(shè)置該window的顯示模式和類型,這就需要理清楚LayoutParams 每個(gè)屬性的含義软舌,以應(yīng)用至多變的需求當(dāng)中才漆。上面所述大都包含了日常開(kāi)發(fā)中所用到的設(shè)置,其它可參照官方文檔 佛点。

參考資料:

官方文檔

個(gè)人博客:

https://fuusy.github.io/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末醇滥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鸳玩,老刑警劉巖焰手,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異怀喉,居然都是意外死亡书妻,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)躬拢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)躲履,“玉大人,你說(shuō)我怎么就攤上這事聊闯」げ拢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵菱蔬,是天一觀的道長(zhǎng)篷帅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)拴泌,這世上最難降的妖魔是什么魏身? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮蚪腐,結(jié)果婚禮上箭昵,老公的妹妹穿的比我還像新娘。我一直安慰自己回季,他們只是感情好家制,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著泡一,像睡著了一般颤殴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鼻忠,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天涵但,我揣著相機(jī)與錄音,去河邊找鬼粥烁。 笑死贤笆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的讨阻。 我是一名探鬼主播芥永,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼钝吮!你這毒婦竟也來(lái)了埋涧?” 一聲冷哼從身側(cè)響起板辽,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棘催,沒(méi)想到半個(gè)月后劲弦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡醇坝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年邑跪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呼猪。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡画畅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宋距,到底是詐尸還是另有隱情轴踱,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布谚赎,位于F島的核電站淫僻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏壶唤。R本人自食惡果不足惜雳灵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望视粮。 院中可真熱鬧细办,春花似錦、人聲如沸蕾殴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钓觉。三九已至,卻和暖如春坚踩,著一層夾襖步出監(jiān)牢的瞬間荡灾,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工瞬铸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留批幌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓嗓节,卻偏偏與公主長(zhǎng)得像荧缘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拦宣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容