* 程序入口 *
系統會啓動SystemUIService
SystemUIService->onCreatejava
SystemUIApplication->startServicesIfNeeded()
建立全部SystemUI爲base的類的對象
調用start()
若是bootCompleted調用onBootCompleted
好比 PhoneStatusBar的start和onBootCompletedandroid
PhoneStatusBar -> BaseStatusBar -> SystemUIapp
繼承於SystemUI的類以下:
extends SystemUI
PhoneStatusBar
KeyBoardUI
KeyguardViewMediator
RingtonePlayer
PowerUI
Recents
ShortcutKeyDispatcher
Divider
BaseStatusBar
SystemBars
TunerService
PipUI
StorageNotification
VolumeUIide
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* view的建立過程 *函數
PhoneStatusBar
->createAndAddWindows建立statusbar的視圖
->addStatusBarWindow 建立StatusbarWindow並追加到WindowManager做爲系統的statusbar動畫
StatusBarWindowView
PhoneStatusbar的成員mStatusBarWindow
其實就是super_status_bar.xmlui
PhoneStatusBarView extends PanelBar
mStatusBarView PhoneStatusBar的成員
對應status_bar.xmlthis
NotificationPanelView
PhoneStatusBar的成員mNotificationPanel
StatusBarWindowView的成員mNotificationPanel
其實就是status_bar_expanded.xmlspa
status_bar_expanded.xml
NotificationsQuickSettingsContainer
NotificationPanelView的成員mNotificationContainerParent
id = notification_container_parent,在status_bar_expanded.xml中.net
AutoReinflateContainer
NotificationPanelView的成員mQsAutoReinflateContainer
id = qs_auto_reinflate_container
構造函數中
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoReinflateContainer);
if (!a.hasValue(R.styleable.AutoReinflateContainer_android_layout)) {
throw new IllegalArgumentException(「AutoReinflateContainer must contain a layout」);
}
mLayout = a.getResourceId(R.styleable.AutoReinflateContainer_android_layout, 0);
實際是經過attrs中
去查找id爲qs_auto_reinflate_container的layout文件中的android:layout屬性對應的layout屬性的值
android:layout=」@layout/qs_panel」
AutoReinflateContainer
inflateLayout();
會回調全部的Listener
一共有3個Listener
PhoneStatusbar中一個
NotificationPanelView中一個
NotificationQuickSettingsContainer中一個
mQsAutoReinflateContainer.addInflateListener(new InflateListener() {
@Override
public void onInflated(View v) {
mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container);
mQsContainer.setPanelView(NotificationPanelView.this);
mQsContainer.getHeader().findViewById(R.id.expand_indicator)
.setOnClickListener(NotificationPanelView.this);
// recompute internal state when qspanel height changes
mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
final int height = bottom - top;
final int oldHeight = oldBottom - oldTop;
if (height != oldHeight) {
onQsHeightChanged();
}
}
});
mNotificationStackScroller.setQsContainer(mQsContainer);
}
});
所以AutoReinflateContainer其實內部就是android:layout=」@layout/qs_panel」
也就是QSContainer,對應qs_panel.xml
qs_panel.xml包含4部分
quick_settings_panel ——>QSPanel quick setting打開狀態
quick_status_bar_expanded_header ——>QuickStatusBarHeader quick setting收起的狀態,包含編輯btn,setting btn,時間等,
最重要的是QuickQSPanel,表明quick setting收起狀態
qs_detail ——>QSDetail quick setting中某一個setting相打開後的狀態,
好比battery或者情景模式設定打開後的詳情狀態
包含兩個btn,一個是more setting,一個是done
點擊done返回QSPanel狀態
點擊more setting進入對應的設定頁面
qs_customize ——>QSCustomizer quick setting detail編輯中的狀態
quick_status_bar_expanded_header
QuickStatusBarHeader.java
實際上是quick_status_bar_expanded_header.xml
這裏面就包含了多個btn,切換用戶,進入setting,下拉打開quick setting詳細,編輯
裏面包含
mHeaderQsPanel = (QuickQSPanel) findViewById(R.id.quick_qs_panel);
quick_qs_panel ——>QuickQSPanel
signal_cluster
status_bar.xml->system_icons.xml->signal_cluster_view.xml->signal_cluster
status_bar.xml是狀態欄
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* QSPanel隱藏過程 *
NotificationPanelView status_bar_expanded.xml id=notification_panel
extends PanelView
PanelView ->mBar->PanelBar->panelExpansionChanged
NotificationPanelView PhoneStatusBarView
PhoneStatusBarView->animateCollapsePanels->
mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
PanelBar的
panelExpansionChanged
經過PanelView的notifyBarPanelExpansionChanged調用的
這裏使得最初顯示了QuickQSPanel,隱藏了QSPanel
啓動時經過BaseStatusBar->start()->createAndAddWindows()建立statusbar的view
以後經過disable
disable(switches[0], switches[6], false /* animate */);
調用PhoneStatusBar的
disable
12-07 15:38:45.695 1389-1389/com.android.systemui D/PhoneStatusBar: disable: < EXPAND* icons alerts system_info BACK* HOME* RECENT* clock SEARCH* quick_settings >
if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {
animateCollapsePanels();
}
}
以後就會調用animateCollapsePanels();
animateCollapsePanels(flags, false /* force /, false / delayed */,
1.0f /* speedUpFactor */);
mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
mStatusBarView是PhoneStatusBarView,
PhoneStatusBarView extends PanelBar
collapsePanel在PanelBar中->PhoneStatusBarView
public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
true,false,1.0
panelView->NotificationPanelView
fling(0, false /* expand /, speedUpFactor, false / expandBecauseOfFalsing */);
fling(0, false, 1.0, false);
flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
flingToHeight(0, false, 0.0f, 1.0, false);
@Override
public void onAnimationEnd(Animator animation) {
if (clearAllExpandHack && !mCancelled) {
setExpandedHeightInternal(getMaxPanelHeight());
}
mHeightAnimator = null;
if (!mCancelled) {
notifyExpandingFinished();
}
notifyBarPanelExpansionChanged();
}
panelView->notifyBarPanelExpansionChanged();
mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f || mPeekPending
|| mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp()
|| mTracking || mHeightAnimator != null);
panelBar->panelExpansionChanged(float frac, boolean expanded) {
12-07 15:38:45.695 1389-1389/com.android.systemui V/PanelBar: panelExpansionChanged: start state=0, frac=0.0, expanded=false
12-07 15:38:45.695 1389-1389/com.android.systemui V/PanelBar: panelExpansionChanged: end state=0 [ fullyClosed ]
PanelView pv = mPanel;
pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
public class NotificationPanelView extends PanelView
NotificationPanelView -> status_bar_expanded.xml裏面包含QSPanel
這裏就將QSPanel隱藏掉了
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
清空全部Notification在
status_bar_notification_dismiss_all.xml中
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tiles每一個tils對應一個quick setting icon
config.xml
wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night
QSTile.java
經過QSTileHost.createTile建立一個tile
TileQueryHelper.java構造函數->addSystemTiles建立全部Tile
構造函數是在QuickStatusBarHeader的onFinishInflate函數中調用的
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
quick_settings_panel ——>QSPanel
裏面包含qs_paged_tile_layout ——>QSTileLayout
裏面的每一個item是QSTileView,包含icon和label,點擊能夠顯示詳情
QuickQSPanel
裏面的每一個item是QSTileBaseView,只有icon,點擊不能顯示詳情
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Notification畫面結構
NotificationContentView
ExpandableNotificationRow ——————————–一行能夠擴展的Notification,包含NotificationChildrenContainer,
NotificationGuts,NotificationSettingsIconRow
在BaseStatusBar的inflateViews建立並賦值給Entry的row變量記錄下來
NotificationChildrenContainer ——————————–包含NotificationHeaderView和Divider
NotificationHeaderView ——————————–包含Notification合併後的header,app icon,name,下拉btn
HybridNotificationView ——————————–ExpandableNotificationRow的兩個成員變量mPrivateLayout和mPublicLayout對應的類
當多條收縮在一塊兒的Notification中的一行收縮顯示時使用這個View
NotificationGuts ——–notification_guts——-一條Notification的設定條目 包含icon title summary
設定相關radio btn,以及設定打開後的more setting和done btn
NotificationSettingsIconRow ——–notification_guts——-彷佛是左右拖動Notification後顯示出的Setting btn
HeadsUpEntry ——————————–從Android 5.0開始,若是notification priority設置爲HIGH, MAX, 或者fullscreenIntent不爲空,在非鎖屏界面收到notification時屏幕上方會顯示一個小懸浮窗口提醒用戶,方便用戶在不退出當前瀏覽界面的前提下快速響應該notification,即Heads-Up Notification(簡稱HUN)。
NotificationViewWrapper implements TransformableView
用於處理view動畫,好比fadeIn fadeOut
BaseStatusBar的inflateViews
row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
parent, false);
ExpandableNotificationRow extends ActivatableNotificationView
ActivatableNotificationView extends ExpandableOutlineView
ExpandableOutlineView extends ExpandableView
ExpandableView extends FrameLayout
因此ExpandableNotificationRow根本上是個FrameLayout
Notification.Builder生成的Notification沒有使用其餘content layout,沒有使用其餘style的話
那麼直接從Notification.Builder建立View
cachedContentView = builder.createContentView();
cachedBigContentView = builder.createBigContentView();
cachedHeadsUpContentView = builder.createHeadsUpContentView();
cachedPublicContentView = builder.makePublicContentView();
實際處理在Notification.java中
frameworks/base/core/java/android/app/Notification.java
主要用到的Layout文件
frameworks/base/core/res/res/layout/notification_template_material_base.xml
frameworks/base/core/res/res/layout/notification_template_right_icon.xml
frameworks/base/core/res/res/layout/notification_template_text.xml
frameworks/base/core/res/res/layout/notification_template_part_line1.xml
frameworks/base/core/res/res/layout/notification_template_header.xml
frameworks/base/core/res/res/layout/notification_template_material_big_base.xml
裏面用到一些文字的style
在
frameworks/base/core/res/res/values/styles_material.xml
@color/white
@dimen/notification_text_size
<style name="TextAppearance.Material.Notification.Reply" />
<style name="TextAppearance.Material.Notification.Title">
<item name="textColor">@color/white</item>
<item name="textSize">@dimen/notification_title_text_size</item>
</style>
<style name="TextAppearance.Material.Notification.Line2">
<item name="textSize">@dimen/notification_subtext_size</item>
</style>
<style name="TextAppearance.Material.Notification.Info">
<item name="textColor">@color/white</item>
<item name="textSize">@dimen/notification_subtext_size</item>
</style>
<style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" />
<style name="TextAppearance.Material.Notification.Emphasis">
<item name="textColor">#66000000</item>
</style>
<style name="Widget.Material.Notification.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />
<style name="Widget.Material.Notification.MessagingText" parent="Widget.Material.Light.TextView">
<item name="layout_width">match_parent</item>
<item name="layout_height">wrap_content</item>
<item name="ellipsize">end</item>
<item name="visibility">gone</item>
<item name="textAppearance">@style/TextAppearance.Material.Notification</item>
</style>
Notification來源
BaseStatusBar.java
start時經過
mNotificationListener.registerAsSystemService(mContext,
new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
UserHandle.USER_ALL);
註冊listener
private final NotificationListenerService mNotificationListener =
new NotificationListenerService() {
@Override
public void onNotificationPosted(final StatusBarNotification sbn,
final RankingMap rankingMap) {
來接收新的Notification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
setSystemUiVisibility
View.STATUS_BAR_TRANSIENT————0x04000000
View.STATUS_BAR_TRANSLUCENT———-0x40000000
View.STATUS_BAR_TRANSPARENT———-0x0000008
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PanelView->flingToHeight 裏面會建立一個動畫進行height變化的動畫 ValueAnimator animator = createHeightAnimator(target);