Statusbar UI结构
Statusbar (传统状态栏条,置顶)
中间为下拉出来的statusbar_expanded
最下方为TrackingView,TrackingView为一整屏背景的View+下拉时出来的把手,一般我们只能看到一个把手,如果expanded里面的通知少,可以看到TrackingView的背景。一开始千万不要以为expanded是全屏的,注意expanded和TrackingView之间区别。
抽象类SystemUI的继承关系:它有两个子类PowerUI、StatusBar
抽象类StatusBar也有两个子类;PhoneStatusBar,TabletStatusBar
SystemUI重要的抽象方法:start(),对于statusBar,它的作用为makeStatusbarView、注册statusbar的接口,初始化statusbar window参数。
makeStatusbarView主要用于生成Statusbar UI结构(inflate 3个 statusbar的layout.xml)
注册statusbar的接口是相当巧妙的一步。
首先说下app如何调用statusbar的接口,比如Launcher的option菜单里面有通知选项,可以展开状态栏,调用如下:
finalStatusBarManager statusBar = (StatusBarManager)getSystemService(STATUS_BAR_SERVICE);
if (statusBar != null) {
statusBar.expand();
}
StatusBarManager声明了所有SDK可以调用的接口。StatusBarManager内部其实使用AIDL(IStatusBarService)接口调用StatusBarManagerService里面的方法。StatusBarManagerService中的方法也并不是直接实现这个接口。而是通过调用AIDL(IStatusBar)的方法,IStatusBar就是在statusBar.start()方法中IStatusBarService .registerStatusBar注册的,传入的IStatusBar参数为CommandQueue类。CommandQueue类是一个将binderthread内的消息转发到main thread里面进行处理的类(根据JavaDoc猜测),目测这个类的作用为在binder thread中减少停留时间,将主要的操作全部投递到另一个线程。这样binder thread里面的消息池就不因为消息太多处理不过来而爆掉。但是,其实CommandQueue还不是最终实现各种接口的类,CommandQueue的构造方法需要传入两个参数,callback和statusBarIconList,CommandQueue通过调用callback和Iconlist的实现来达到最终实现状态栏接口实现。Callback传入的是this,表示有statusbar的子类负责实现状态栏的接口。statusBarIconList为new了一个statusBarIconList。
初始化statusbarwindow参数:主要初始化statusbarlayoutparam,然后addView,放到屏幕上。
状态栏下拉效果代码在PhoneStatusBar.interceptTouchEvent(MotionEvent)中。
performCollpase();
performExpand();
mExpand;
performTrack();
mTracking
statusbar 置顶状态栏UI结构
StatusBarView extends FrameLayout
正常待机情况,无通知arrive
Notification Class:IconMerger LinearLayout |
StatusbarIcons LinearLayout |
Clock com.android.systemui.statusbar.Clock |
通知arrive
TickerView(一整条占满) |
进入短信、拨号、通话界面(MTK专有)
SIMIndicator |
||
Notification Class:IconMerger LinearLayout |
StatusbarIcons LinearLayout |
Clock com.android.systemui.statusbar.Clock |
下拉状态栏后
com.android.systemui.statusbar.DateView |
||
Notification Class:IconMerger LinearLayout |
StatusbarIcons LinearLayout |
Clock com.android.systemui.statusbar.Clock |
由于StatusBarView是FrameLayout,所以以上表格第一项会覆盖第二项表格的内容。因此,如果layout里面没有处理好,那么很可能造成下面的icon显示不全
IconMerger:功能:负责通知icon的管理
当通知栏的宽度无法显示所有通知icon时,在通知栏最左方会显示moreIconView。并会附上所有通知的数量。
关键方法:onLayout
1、获取maxWidth (width= r - l)这个就是通知栏最大的宽度。
2、计算出除moreIconView之外所有通知icon,能放下它们所需要的空间 fitLeft,fitRight
3、如果fitRight – fitLeft < maxWidth-moreIconView_width(表示目前宽度足够放下所有通知icon),那么隐藏moreIconView(注意,不是用setVisibility(Gone),而是用layout(0,top,0,bottom))
4、计算breakingPoint,这个值表示如果通知icon的左边界超过这个point,那么它将显示不全,应该隐藏。否则layout这个icon。
StatusBarView,整个置顶状态栏View,其实只是个容器+ StatusBarService的宿主。
关键函数:
onLayout:主要是对DateView进行处理。
由于DateView是覆盖statusbar三件套上面,所以必须有指定好适合的长度,以免覆盖时发生覆盖不全,下方icon露半个小脸。
getDateSize:给DateView指定一个合适的右边界。
算法:遍历传入的ViewGroup的各个children,寻找DateView真实右边界所在的区间