1. 介紹
Android中的Statusbar包含導航欄(NavigationBar, 位於左側、右側或者底部)和狀態欄(StatusBar, 位於頂部, 可下拉)兩個部分, 位於SystemUI(frameworks/base/packages/SystemUI)模塊
2. 初始化
SystemServer::startOtherServices() SystemServer::startSystemUi("com.android.systemui.SystemUIService") SystemUIService::onCreate() /* * 加載並啟動config_systemUIServiceComponents定義的服務列表 * frameworks/base/packages/SystemUI/res/values/config.xml * <!-- SystemUI Services: The classes of the stuff to start. --> * <string-array name="config_systemUIServiceComponents" translatable="false"> * <item>com.android.systemui.Dependency</item> * <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item> * ...... * <item>com.android.systemui.SystemBars</item> * ...... * <item>com.android.systemui.keyboard.KeyboardUI</item> * ...... * </string-array> */ SystemUIApplication::startServicesIfNeeded() com.android.systemui.SystemBars::start() /* * 啟動config_statusBarComponent定義的服務 * frameworks/base/packages/SystemUI/res/values/config.xml * <string name="config_statusBarComponent" translatable="false"> * com.android.systemui.statusbar.phone.StatusBar * </string> * * 在Automotive中被overlay, CarStatusBar繼承自StatusBar * <string name="config_statusBarComponent" translatable="false"> * com.android.systemui.statusbar.car.CarStatusBar * </string> */ SystemBars::createStatusBarFromConfig() CarStatusBar::start() StatusBar::start() StatusBar::createAndAddWindows() StatusBar::addStatusBarWindow() CarStatusBar::makeStatusBarView() StatusBar::makeStatusBarView() ---------------------------------------------------------------------------- +++ NavigationBar +++ ---------------------------------------------------------------------------- WindowManagerService::hasNavigationBar() /* * frameworks/base/core/res/res/values/config.xml * <bool name="config_showNavigationBar">false</bool> * * 在Automotive中被overlay * <bool name="config_showNavigationBar">true</bool> */ PhoneWindowManager::hasNavigationBar() CarStatusBar::createNavigationBar() /* * frameworks/base/packages/SystemUI/res/values/config.xml * 根據如下配置決定是導航欄的位置,Automotive中會被overlay * config_enableBottomNavigationBar * config_enableLeftNavigationBar * config_enableRightNavigationBar * 然后通過WindowManager::addView()添加創建窗口 * WindowManager.LayoutParams.TYPE_NAVIGATION_BAR * WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL */ CarStatusBar::buildNavBarWindows() CarStatusBar::buildNavBarContent() CarStatusBar::attachNavBarWindows() ---------------------------------------------------------------------------- +++ StatusBar +++ ---------------------------------------------------------------------------- /* 加載super_status_bar.xml實例化為狀態欄的根控件 */ StatusBar::inflateStatusBarWindow() /* * 通過WindowManager::addView()添加窗口, 類型如下 * WindowManager.LayoutParams.TYPE_STATUS_BAR */ StatusBarWindowManager::add()
3. 顯示和隱藏
3.1 應用實例
應用可以通過如下的方式隱藏狀態欄和導航欄
// Android < 4: getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 4 =< Android < 11: int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; getWindow().getDecorView().setSystemUiVisibility(uiFlags); // Android >= 11 /* * systemBars包含statusBars和navigationBars */ controller.hide(WindowInsetsCompat.Type.systemBars()) controller.show(WindowInsetsCompat.Type.systemBars())
3.2 調用流程
View::setSystemUiVisibility() ViewRootImpl::recomputeViewAttributes() ViewRootImpl::scheduleTraversals() ViewRootImpl::doTraversal() ViewRootImpl::performTraversals() ViewRootImpl::collectViewAttributes() View::dispatchCollectViewAttributes() View::performCollectViewAttributes() // Do Something View::dispatchWindowSystemUiVisiblityChanged() ViewRootImpl::relayoutWindow() IWindowSession::relayout() com.android.server.wm.Session::relayout() WindowManagerService::relayoutWindow() PhoneWindowManager::adjustWindowParamsLw() ---------------------------------------------------------------------------- +++ How to get here +++ ---------------------------------------------------------------------------- PhoneWindowManager::updateSystemUiVisibilityLw() StatusBarManagerService::setSystemUiVisibility() IStatusBar::setSystemUiVisibility() CommandQueue::setSystemUiVisibility() StatusBar::setSystemUiVisibility() StatusBar::notifyUiVisibilityChanged() WindowManagerService::statusBarVisibilityChanged() PhoneWindowManager::adjustSystemUiVisibilityLw() WindowManagerService::updateStatusBarVisibilityLocked() InputManagerService::setSystemUiVisibility() DisplayContent::updateSystemUiVisibility() ViewRootImpl::W::dispatchSystemUiVisibilityChanged() ViewRootImpl::dispatchSystemUiVisibilityChanged() ViewRootImpl::handleDispatchSystemUiVisibilityChanged() View::updateLocalSystemUiVisibility() View::dispatchSystemUiVisibilityChanged() OnSystemUiVisibilityChangeListener::onSystemUiVisibilityChange()
參考:
<Android 9.0 SystemUI分析>
<StatusBar狀態欄部分功能記錄>
<Android 顯示、隱藏狀態欄和導航欄>
<Android SystemUI(一):圖文並茂的介紹>
<API 30新特性:WindowInsetsController>