Android 12 源碼分析 —— 應(yīng)用層 四(SystemUI的基本布局設(shè)計及其基本概念)
更新歷史 | 日期 | 內(nèi)容 |
---|---|---|
1 | 2023-9-11 | 增加文中提及的漸變動畫的效果圖 |
在上兩篇文章中,我們介紹SystemUI的啟動過程,以及基本的組件依賴關(guān)系?;镜囊蕾囮P(guān)系請讀者一定要掌握,因為后面的文章,將會時常出現(xiàn)這些依賴關(guān)系的使用,屆時將會一筆帶過,而不會詳細(xì)說明他們的實現(xiàn)細(xì)節(jié)和原理。
接下來我們將介紹,SystemUI中各個UI部分是如何被加入屏幕中的,以及查看下拉狀態(tài)中的各個圖標(biāo)的實現(xiàn)。
但是在進(jìn)入真正的主題之前,我們還需要了解SystemUI中的各個UI的基本布局以及名字,只有了解了這些基本布局和名字,才能夠在許多相似名字中分清楚具體的對象是誰。
接下來我們將介紹SystemUI的基本布局設(shè)計,看看整個SystemUI的布局被大致分成了哪些內(nèi)容,以及這些內(nèi)容對應(yīng)的業(yè)務(wù)是什么。
SystemUI的window劃分
在“Android 12 源碼分析 —— 應(yīng)用層 二(SystemUI大體組織和啟動過程)http://t.csdn.cn/chk6Y”文章中,我們提及過,SystemUI可以通過WindowManager來顯示自己的UI。
事實上,SystemUI正是通過WindowManager來添加自己的主要的UI視圖。在SystemUI中,將以下幾個部分,分別放置在不同的Window中,然后通過WindowManager將其添加到屏幕上。
- StatusBar——狀態(tài)欄
- NotificationShade——通知卷簾(我們常說的下拉狀態(tài)欄)
- NavigationBar——導(dǎo)航欄
注意:除了上面三個常見的window以外,還有其他的window,如GlobalActionDialog(負(fù)責(zé)顯示——關(guān)機(jī),重啟的彈框),VolumeDialog(顯示音量調(diào)節(jié)),這些window將會在我們介紹各個子主題的時候,依次登場
可能會有讀者疑惑:鎖屏呢?不在一個單獨window下面嗎?事實上,鎖屏不在一個單獨的window中,其本身就是NotificationShade(通知卷簾,即下拉狀態(tài)欄)。換句話說,鎖屏的內(nèi)容和下拉狀態(tài)欄的內(nèi)容在同一個window中。
這里一定要注意的一點是:對應(yīng)的中文命名方式,從此刻開始,將在對應(yīng)的類后面用小括號標(biāo)記其中文命名,之所以有這樣的標(biāo)記,是因為英文名字有很多相似之處,可能不利于記憶,如:StatusBar雖然叫做狀態(tài)欄,但是在不同的Window中有不同的StatusBar(狀態(tài)欄),比如,在鎖屏狀態(tài)下有KeyguardViewStatusBar(鎖屏狀態(tài)欄);同樣地,在NotificationShade(通知卷簾,即下拉狀態(tài)欄)中本應(yīng)該顯示StatusBar(狀態(tài)欄)的地方,并不叫StatusBar。而為了便于記憶,將其中文名字放在小括號中
為了便于理解,現(xiàn)在window標(biāo)記出來,如下:
有了上面的直觀感受,我們將結(jié)合SystemUI的layout文件,大體的介紹其UI布局及其相關(guān)概念,有了這些概念,才能夠在紛繁復(fù)雜的源碼中,找到對應(yīng)的實現(xiàn)實體。
SystemUI的命名規(guī)則和設(shè)計模式
本文主題是SystemUI的布局介紹,但依然可能會存在這樣的疑問:這些布局是什么時候被加載的?他們的加載流程是怎樣的?
在后面的文章中,我們會依次介紹這些布局的加載,以及怎么處理各種事件,但再此之前,需要明白他們之間的設(shè)計模式和命名規(guī)則。
SystemUI各個小模塊采用:MVC,MVP等設(shè)計模式,因此在他們的命名體系中,經(jīng)常以xxxView,xxxController,xxxPresenter來代表。例如,代表StatusBar(狀態(tài)欄)的StatusBarWindowView(狀態(tài)欄窗口視圖),StatusBarWindowController(狀態(tài)欄窗口控制器),而與StatusBarWindow相關(guān)的model即為StatusBar(狀態(tài)欄)
當(dāng)然,SystemUI編輯歷史長,中間有幾次大的修改,并不是所有的類,都遵循這些規(guī)則,不過讀者在閱讀源碼的時候,可以按照這些思路進(jìn)行思考。
而本文以介紹SystemUI布局為主題,而不關(guān)心這些布局的加載時刻和流程,但我們會用一段小提示來,簡略的概括這些布局的加載流程。在閱讀這些簡略加載流程的時候,會出現(xiàn)很多相似的名字,因此可以按照上面的命名規(guī)則來對應(yīng)相應(yīng)的實體
讀者可以忽略這些加載流程,因為在后續(xù)的文章中,將會詳細(xì)的介紹這些UI的加載流程和用戶操作
我們先從最復(fù)雜的NotificationShade(通知卷簾,下拉狀態(tài)欄)介紹起。
SystemUI的NotificationShade(通知卷簾,即下拉狀態(tài)欄)window的詳細(xì)布局
NotificationShade(通知卷簾,即下拉狀態(tài)欄)window的的加載流程
按照上文的說明,會先簡略介紹,這個布局的加載流程,如下:
- SytemUIService啟動之后,調(diào)用SystemUIApplication的startServicesIfNeeded()啟動相應(yīng)的服務(wù)(“Android 12 源碼分析 —— 應(yīng)用層 二(SystemUI大體組織和啟動過程)http://t.csdn.cn/chk6Y”)
- 啟動的服務(wù)中,有一個叫做StatusBar,它會在第一步中,被調(diào)用start()方法
- 在start()方法中,會調(diào)用createAndAddWindows()方法
- createAndAddWindows()方法會調(diào)用makeStatusBarView()方法
- makeStatusBarView()方法會調(diào)用inflateStatusBarWindow()方法
- inflateStatusBarWindow()方法會調(diào)用SuperStatusBarViewFactory的getNotificationShadeWindowView()方法
- getNotificationShadeWindowView()方法會去加載并解析R.layout.super_notification_shade,也即super_notification_shade.xml
- 第7步完成之后,會回到第4步中,并調(diào)用NotificationShadeWindowController的attach()方法,將對應(yīng)的UI,添加到屏幕上
注意:對于上面的調(diào)用過程,讀者可以完全不用在意,因為后面的文章,將會詳細(xì)介紹
接下來分析,super_notification_shade.xml
NotificationShade(通知卷簾,即下拉狀態(tài)欄)window的頂層視圖
super_notification_shade.xml的源文件如下:
注意:為了減輕閱讀障礙,我會省略掉一些非常常見的代碼,如一些屬性的定義和賦值,省略一些非常簡單的布局視圖
<com.android.systemui.statusbar.phone.NotificationShadeWindowView>
<com.android.systemui.statusbar.BackDropView>
</com.android.systemui.statusbar.BackDropView>
<com.android.systemui.scrim.ScrimView
android:id="@+id/scrim_behind" />
<com.android.systemui.scrim.ScrimView
android:id="@+id/scrim_notifications"/>
<com.android.systemui.statusbar.LightRevealScrim
android:id="@+id/light_reveal_scrim" />
<include layout="@layout/status_bar_expanded"/>
<include layout="@layout/brightness_mirror_container" />
<com.android.systemui.scrim.ScrimView
android:id="@+id/scrim_in_front" />
<!-- Keyguard messages -->
<FrameLayout>
<com.android.keyguard.KeyguardMessageArea
android:id="@+id/keyguard_message_area"/>
</FrameLayout>
<com.android.systemui.biometrics.AuthRippleView/>
</com.android.systemui.statusbar.phone.NotificationShadeWindowView>
從上面的代碼結(jié)構(gòu)看,非常滴簡單,我們依次介紹如下:
-
NotificationShadeWindowView:通知卷簾窗口,即下拉狀態(tài)欄窗口的最頂層視圖
-
BackDropView:幕布視圖,它會顯示最最底部的一些背景,如播放音樂的時候,顯示音樂的專輯圖片
-
ScrimView:總共有三個,他們主要負(fù)責(zé)遮罩,如在鎖屏狀態(tài)下,整個鎖屏界面,稍微變暗淡一些,即通過設(shè)置遮罩的透明度來實現(xiàn)
-
LightRevealScrim:也是遮罩相關(guān)的視圖,它負(fù)責(zé)處理一些漸變的動畫,如在設(shè)置中打開息屏顯示,那么在點擊電源按鈕的時候,將會顯示對應(yīng)的動畫,如下圖
-
status_bar_expanded.xml:即展開的狀態(tài)中的布局,這里面詳細(xì)列出了下拉狀態(tài)欄之后,應(yīng)該顯示哪些內(nèi)容
-
brightness_mirror_container.xml:這個是調(diào)節(jié)亮度條對應(yīng)的鏡像視圖,因為還有一個亮度調(diào)節(jié)條他在status_bar_expanded中,之所以有這個,是為了在調(diào)節(jié)亮度的時候,隱藏status_bar_expanded中的內(nèi)容
-
KeyguardMessageArea:鎖屏信息顯示區(qū)域,如輸入pin錯誤,則會在此處顯示wrong pin
除了第七點,可以直接給出參考圖以外,其他的都無法給出特別好的參考圖,因此可以使用文末推薦的布局查看工具,進(jìn)行查看
在上面中出現(xiàn)了兩個include的xml文件,如果每個文件都介紹,將會消耗大量的篇幅,同時又有些詳略不得當(dāng),因此,針對一些簡單的layout文件,將會一筆帶過,如上面的brightness_mirror_container.xml文件。而這些略過的文件,在某些子主題下,將會詳細(xì)介紹,如上面的brightness_mirror_container.xml將會在調(diào)節(jié)音量的文章中,詳細(xì)介紹
因此接下來將會介紹status_bar_expanded.xml文件
status_bar_expanded.xml文件分析
status_bar_expanded.xml文件原文如下:
注意:這里依然會省略掉一些屬性定義和賦值
<com.android.systemui.statusbar.phone.NotificationPanelView
android:id="@+id/notification_panel">
<FrameLayout
android:id="@+id/big_clock_container" />
<ViewStub
android:id="@+id/keyguard_qs_user_switch_stub"/>
<include
layout="@layout/keyguard_bottom_area"
android:visibility="gone" />
<ViewStub
android:id="@+id/keyguard_user_switcher_stub" />
<include layout="@layout/status_bar_expanded_plugin_frame"/>
<include layout="@layout/dock_info_bottom_area_overlay" />
<com.android.keyguard.LockIconView
android:id="@+id/lock_icon_view">
</com.android.keyguard.LockIconView>
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
android:id="@+id/notification_container_parent">
<include layout="@layout/keyguard_status_view"/>
<include layout="@layout/dock_info_overlay" />
<FrameLayout android:id="@+id/qs_frame"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/qs_edge_guideline"/>
<com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
android:id="@+id/notification_stack_scroller"/>
<include layout="@layout/ambient_indication"
android:id="@+id/ambient_indication_container" />
<include layout="@layout/photo_preview_overlay" />
<include
layout="@layout/keyguard_status_bar"
android:visibility="invisible" />
<Button
android:id="@+id/report_rejected_touch"/>
<com.android.systemui.statusbar.phone.TapAgainView
android:id="@+id/shade_falsing_tap_again"/>
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
<FrameLayout
android:id="@+id/preview_container">
</FrameLayout>
</com.android.systemui.statusbar.phone.NotificationPanelView>
對上面文件的介紹如下:
- NotificationPanelView:整個通知欄和快速設(shè)置圖標(biāo)的頂層目錄
- id為big_clock_container的FrameLayout:顯示一個較大的時鐘視圖
- 兩個ViewStub:這個跟多用戶的切換視圖有關(guān),當(dāng)點擊多用戶的時候,會在這兩個ViewStub之一中,顯示切換的視圖
- keyguard_bottom_area.xml:顯示鎖屏底部區(qū)域,如充電中…
- status_bar_expanded_plugin_frame.xml:跟SystemUI的插件有關(guān),現(xiàn)在讀者可以不用管,后面會詳細(xì)介紹其細(xì)節(jié)
- dock_info_bottom_area_overlay.xml:空的
- LockIconView:鎖屏界面下的鎖圖標(biāo)
- NotificationsQuickSettingsContainer:通知和快速設(shè)置的容器,其中顯示通知和快速設(shè)置
- keyguard_status_view.xml:顯示鎖屏相關(guān)的狀態(tài)視圖,如顯示日期
- dock_info_overlay.xml: 空的
- id為qs_frame的FrameLayout:用于快速設(shè)置的父容器
- Guideline:用于調(diào)整布局的視圖
- NotificationStackScrollLayout:用于顯示通知的父容器
- ambient_indication.xml:空的
- photo_preview_overlay.xml:空的
- keyguard_status_bar.xml:鎖屏狀態(tài)下的,狀態(tài)欄
- Button:調(diào)試使用,不用管
- TapAgainView:顯示,再按一次的視圖,現(xiàn)在已經(jīng)不用了
- id為preview_container的FrameLayout:預(yù)覽圖片顯示視圖,如滑動相機(jī)圖片,會先顯示一個相機(jī)的圖片
注意:對于上面某些xml文件的說明為:空的,一方面,部分內(nèi)容已經(jīng)不再使用,另一方面,部分內(nèi)容將會在后續(xù)文章中出現(xiàn)。
在上面的xml文件中,細(xì)心的讀者可能已經(jīng)注意到,即鎖屏也是在NotificationShade窗口中的。為了能夠直觀的觀察上面的內(nèi)容,我們使用圖片進(jìn)行說明,如下圖:
在上面的源碼中,出現(xiàn)了
- keyguard_bottom_area.xml
- status_bar_expanded_plugin_frame.xml
- dock_info_bottom_area_overlay.xml
- keyguard_status_view.xml
- dock_info_overlay.xml
- ambient_indication.xml
- photo_preview_overlay.xml
- keyguard_status_bar.xml
在上面文件,其中status_bar_expanded_plugin_frame.xml,dock_info_bottom_area_overlay.xml,dock_info_overlay.xml,ambient_indication.xml,photo_preview_overlay.xml一部分沒有被使用,一部分將會在后面的子主題中介紹,現(xiàn)在略過并不影響閱讀和理解
剩下的keyguard_bottom_area.xml,keyguard_status_view.xml和keyguard_status_bar.xml三個文件,簡單明了,能夠非常容易的將UI對應(yīng)上,因此不在此處介紹。這并不影響本文的閱讀和理解。不過不用擔(dān)心,在后續(xù)的文章中,我們還會介紹這三個文件,看看他們的交互和初始化過程,此處為了整體行文的緊湊,將其略去
雖然我們已經(jīng)能夠?qū)㈡i屏相關(guān)的UI和代碼建立一個聯(lián)系,但是我們現(xiàn)在還不能將下拉設(shè)置中的UI和代碼建立聯(lián)系。接下來,我們處理這部分內(nèi)容。
QuickSettings(快速設(shè)置)的布局分析
在上面的代碼中,已經(jīng)介紹了id為qs_frame的FrameLayout將用來顯示快速設(shè)置,接下來看看他們是如何布局的。
注意:NotificationStackScrollLayout的布局細(xì)節(jié)將會在后文中詳解
QuickSettings的加載流程
在上文我們知道,id為qs_frame的FrameLayout并沒有使用include來加載一個layout,因為我們需要先簡單說明一下,其加載過程,然后在看其布局結(jié)構(gòu)
- SytemUIService啟動之后,調(diào)用SystemUIApplication的startServicesIfNeeded()啟動相應(yīng)的服務(wù)(“Android 12 源碼分析 —— 應(yīng)用層 二(SystemUI大體組織和啟動過程)http://t.csdn.cn/chk6Y”)
- 啟動的服務(wù)中,有一個叫做StatusBar,它會在第一步中,被調(diào)用start()方法
- 在start()方法中,會調(diào)用createAndAddWindows()方法
- createAndAddWindows()方法會調(diào)用makeStatusBarView()方法
- makeStatusBarView()方法會找到id為qs_frame的FrameLayout并向其中添加一個QSFragment
- QSFragment會去加載qs_panel.xml文件,而這個文件,正是我們的快速設(shè)置的布局文件
qs_panel.xml文件分析
qs_panel.xml原文如下:
<com.android.systemui.qs.QSContainerImpl
android:id="@+id/quick_settings_container" >
<com.android.systemui.qs.NonInterceptingScrollView
android:id="@+id/expanded_qs_scroll_view">
<com.android.systemui.qs.QSPanel
android:id="@+id/quick_settings_panel">
<include layout="@layout/qs_footer_impl" />
</com.android.systemui.qs.QSPanel>
</com.android.systemui.qs.NonInterceptingScrollView>
<include layout="@layout/quick_status_bar_expanded_header" />
<include android:id="@+id/qs_detail" layout="@layout/qs_detail" />
<include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
android:visibility="gone" />
</com.android.systemui.qs.QSContainerImpl>
- QSContainerImpl:快速設(shè)置的父容器
- NonInterceptingScrollView:快速設(shè)置中各個圖標(biāo)的ScrollView
- QSPanel:QSPanel展示里面具體的詳情
- qs_footer_impl.xml:快速設(shè)置底部的顯示視圖,如編輯快速設(shè)置的圖標(biāo),見后面圖片的對應(yīng)關(guān)系
- quick_status_bar_expanded_header.xml:快速設(shè)置中的頭部區(qū)域,見下面的圖片設(shè)置
- qs_detail.xml:快速設(shè)置的詳細(xì)信息
- qs_customize.xml:編輯快速設(shè)置的界面
為了能夠方便的對應(yīng)起來,見下面的圖片
在這里插入圖片描述
在上面的圖片中我們可以看到,QSPanel內(nèi)部,將會有有各種各樣的快速設(shè)置的小圖標(biāo),而這些圖標(biāo)被稱為QSTile.
我們將會在QSPanel的源碼分析中,詳細(xì)講解他們的加載過程。本文旨在介紹SystemUI的布局設(shè)計,而非對某個UI的具體細(xì)節(jié)。
介紹完了qs_frame的布局以后,我們還需要查看該window下面的最后一個布局NotificationStackScrollLayout
NotificationStackScrollLayout布局分析
NotificationStackScrollLayout是一個類,它也沒有使用include來引用其他的布局文件,而其內(nèi)部則是通過其他的方式來添加布局的。
NotificationStackScrollLayout加載通知布局的流程
- 當(dāng)系統(tǒng)有通知到來時,調(diào)用NotificationListener的onNotificationPosted()方法
- 在onNotificationPosted方法中,會通知NotificationEntryManager的mNotifiListener的onNotificationPosted()方法
- 在該方法中,會調(diào)用addNotification()方法,然后在addNotification()中調(diào)用addNotificationInternal()方法
- 在addNotificationInternal()方法中,會調(diào)用NotificationRowBinderImpl的inflateViews()方法
- 在這個方法中,會去調(diào)用RowInFlaterTask的inflate()方法
- 在inflate()方法中,會去加載status_bar_notification_row.xml文件
接下來我們看看這個文件的內(nèi)容
status_bar_notification_row.xml文件解析
status_bar_notification_row.xml文件的原文如下:
<com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
android:id="@+id/expandableNotificationRow">
<!--只有一個ExpandableNotificationRow-->
</com.android.systemui.statusbar.notification.row.ExpandableNotificationRow>
只有一項內(nèi)容,當(dāng)然其內(nèi)部的內(nèi)容,我們現(xiàn)在不需要關(guān)系,ExpandableNotificationRow是我們觀察的最小布局,因為其內(nèi)部已經(jīng)涉及具體的內(nèi)容該怎么顯示了,現(xiàn)在我們只需要領(lǐng)略大概的布局,并明白相關(guān)的概念
- ExpandableNotificationRow:一個可展開的通知
注意:對于通知的排序,優(yōu)先級等,我們將在后面的文章中,一一介紹,此處只需了解整體布局和基本概念即可
至此,NotificationShade窗口的布局介紹基本已經(jīng)完成,在這里面我們熟悉了各個UI的實體,當(dāng)然也省略了一些UI的實體,
省略的部分,將會在后面文章的子主題中,詳細(xì)介紹。
接下來我們接續(xù)查看剩下的兩個window——StatusBar和NavigationBar
StatusBar(狀態(tài)欄)Window的詳細(xì)布局
StatusBar(狀態(tài)欄)window的加載流程
先簡單介紹其加載流程
- SytemUIService啟動之后,調(diào)用SystemUIApplication的startServicesIfNeeded()啟動相應(yīng)的服務(wù)(“Android 12 源碼分析 —— 應(yīng)用層 二(SystemUI大體組織和啟動過程)http://t.csdn.cn/chk6Y”)
- 啟動的服務(wù)中,有一個叫做StatusBar,它會在第一步中,被調(diào)用start()方法
- 在start()方法中,會調(diào)用createAndAddWindows()方法
- createAndAddWindows()方法會調(diào)用makeStatusBarView()方法
- makeStatusBarView()方法中,會調(diào)用inflateStatusBarWindow()方法
- 在inflateStatusBarWindow()方法中,會通過StatusBarComponent的getStatusBarWindowController()方法得到StatusBarWindowController
- 在StatusBarWindowController的構(gòu)造函數(shù)中,會調(diào)用SuperStatusBarViewFactory的getStatusBarWindow()方法
- 而SuperStatusBarViewFactory的getStatusBarWindow()方法將會去加載super_status_bar.xml文件
- 在第四步的createAndAddWindows()方法中,會調(diào)用StatusBarWindowController的attach()方法,將其添加到屏幕上
接下來看看StatusBar(狀態(tài)欄)的布局文件
StatusBar(狀態(tài)欄)Window的頂層視圖
super_status_bar.xml的源文件如下:
<com.android.systemui.statusbar.phone.StatusBarWindowView>
<FrameLayout
android:id="@+id/status_bar_launch_animation_container"/>
<FrameLayout
android:id="@+id/status_bar_container" />
</com.android.systemui.statusbar.phone.StatusBarWindowView>
非常,非常的清爽??!
- StatusBarWindow:表示了狀態(tài)欄的最頂層視圖
- id為status_bar_launch_animation_container的FrameLayout:在這里面顯示動畫,例如:從StatusBar(狀態(tài)欄)中啟動一個Activity時的動畫顯示區(qū)域
- id為status_bar_contianer的FrameLayout:這就是現(xiàn)實狀態(tài)欄內(nèi)容的主要區(qū)域
接下來我們查看其詳細(xì)細(xì)節(jié)
StatusBar(狀態(tài)欄)的布局分析
上面id為status_bar_contianer是一個FrameLayout,我們來看看其如何加載布局的。先簡單介紹其布局加載流程
StatusBar(狀態(tài)欄)布局加載流程
- SytemUIService啟動之后,調(diào)用SystemUIApplication的startServicesIfNeeded()啟動相應(yīng)的服務(wù)(“Android 12 源碼分析 —— 應(yīng)用層 二(SystemUI大體組織和啟動過程)http://t.csdn.cn/chk6Y”)
- 啟動的服務(wù)中,有一個叫做StatusBar,它會在第一步中,被調(diào)用start()方法
- 在start()方法中,會調(diào)用createAndAddWindows()方法
- createAndAddWindows()方法會調(diào)用makeStatusBarView()方法
- makeStatusBarView()方法,會將CollapsedStatusBarFragment放入id為status_bar_container的FrameLayout中
- 而CollapsedStatusBarFragment會在其onCreateView的時候,加載并初始化status_bar.xml文件
status_bar.xml文件分析
status_bar.xml文件原文如下:
<com.android.systemui.statusbar.phone.PhoneStatusBarView
android:id="@+id/status_bar">
<ImageView
android:id="@+id/notification_lights_out"/>
<LinearLayout android:id="@+id/status_bar_contents">
<FrameLayout>
<include layout="@layout/heads_up_status_bar_layout" />
<LinearLayout
android:id="@+id/status_bar_left_side">
<ViewStub
android:id="@+id/operator_name"/>
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"/>
<include layout="@layout/ongoing_call_chip" />
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area"/>
</LinearLayout>
</FrameLayout>
<!-- Space should cover the notch (if it exists) and let other views lay out around it -->
<android.widget.Space
android:id="@+id/cutout_space_view" />
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/centered_icon_area"/>
<com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area">
<include layout="@layout/system_icons" />
</com.android.keyguard.AlphaOptimizedLinearLayout>
</LinearLayout>
<ViewStub
android:id="@+id/emergency_cryptkeeper_text"/>
</com.android.systemui.statusbar.phone.PhoneStatusBarView>
- PhoneStatusBarView:狀態(tài)欄內(nèi)容的父容器
- 當(dāng)狀態(tài)欄被請求以SYSTEM_UI_FLAG_LOW_PROFILE模式顯示時,這個視圖負(fù)責(zé)顯示一個小點
- id為status_bar_content的LinearLayout:顯示狀態(tài)欄內(nèi)容
- heads_up_status_bar_layout.xml:處在StatusBar中的部分提示信息
- id為status_bar_left_side的LinearLayout:狀態(tài)欄左邊的顯示區(qū)域
- Space:填充中間的空白區(qū)域
- AlphaOptimizedFrameLayout:中心圖標(biāo)顯示區(qū)域
- AlphaOptimizedLinearLayout:系統(tǒng)圖標(biāo)顯示區(qū)域,如電量百分比
- id為emergency_cryptkeeper_text的ViewStub:顯示只能撥打緊急呼救電話
從上面的布局文件可以看到,StatusBar(狀態(tài)欄)大致分成了三個區(qū)域,左,中,右,現(xiàn)在只需要了解其中大體布局即可,即能夠在閱讀源碼的時候,知道源碼中的View指的是哪一部分區(qū)域即可。在后面的文章中,我們將詳細(xì)介紹這些布局的內(nèi)容和實現(xiàn)細(xì)節(jié)。
至此,我們了解了,SystemUI中,最重要的兩個Window的布局。剩下最后一個Window即NavigationBar,因為其布局的簡單,我們將在分析Android導(dǎo)航手勢的時候,一并介紹
本文,只需要掌握如下幾個概念即可,因為后面的系列文章,還會反復(fù)提及:
- SystemUI的Window的劃分
- SystemUI的各個UI的名字如,NotificationShadeView,QS等等
- 知道對應(yīng)的View的Controller的名字,大概會是什么樣子,如NotificationShadeWindowView的Controller,應(yīng)該叫做NotificationShadeWindowViewController,反之亦然
因為最近身體欠佳,加之已經(jīng)開學(xué),學(xué)業(yè)繁重,行文倉促,難免有些錯誤,忘看到的讀者給予提醒,謝謝先。
補(bǔ)充:布局查看工具
讀者可使用下面的工具,進(jìn)行相應(yīng)的布局查看文章來源:http://www.zghlxwxcb.cn/news/detail-719717.html
- 老版本DDMS,的hierarchy view
- Android Studio的YALI(通過插件市場安裝)
- Android Studio的Legacy Layout Inspector(通過插件市場安裝)
至于Android Studio自帶的Layout Inspector就不推薦使用了。文章來源地址http://www.zghlxwxcb.cn/news/detail-719717.html
到了這里,關(guān)于Android 12 源碼分析 —— 應(yīng)用層 四(SystemUI的基本布局設(shè)計及其基本概念)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!