我是靠谱客的博主 无语金针菇,最近开发中收集的这篇文章主要介绍Android7.0 SystemUI StatusBar和Notification代码浅析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

* 程序入口 * 
系统会启动SystemUIService 
SystemUIService->onCreate

SystemUIApplication->startServicesIfNeeded() 
创建所有SystemUI为base的类的对象 
调用start() 
如果bootCompleted调用onBootCompleted 
比如 PhoneStatusBar的start和onBootCompleted

PhoneStatusBar -> BaseStatusBar -> SystemUI

继承于SystemUI的类如下: 
extends SystemUI 
PhoneStatusBar 
KeyBoardUI 
KeyguardViewMediator 
RingtonePlayer 
PowerUI 
Recents 
ShortcutKeyDispatcher 
Divider 
BaseStatusBar 
SystemBars 
TunerService 
PipUI 
StorageNotification 
VolumeUI

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
* view的创建过程 *

PhoneStatusBar 
->createAndAddWindows创建statusbar的视图 
->addStatusBarWindow 创建StatusbarWindow并追加到WindowManager作为系统的statusbar

StatusBarWindowView 
PhoneStatusbar的成员mStatusBarWindow 
其实就是super_status_bar.xml

PhoneStatusBarView extends PanelBar 
mStatusBarView PhoneStatusBar的成员 
对应status_bar.xml

NotificationPanelView 
PhoneStatusBar的成员mNotificationPanel 
StatusBarWindowView的成员mNotificationPanel 
其实就是status_bar_expanded.xml

status_bar_expanded.xml 
NotificationsQuickSettingsContainer 
NotificationPanelView的成员mNotificationContainerParent 
id = notification_container_parent,在status_bar_expanded.xml中

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);
 

最后

以上就是无语金针菇为你收集整理的Android7.0 SystemUI StatusBar和Notification代码浅析的全部内容,希望文章能够帮你解决Android7.0 SystemUI StatusBar和Notification代码浅析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部