本文是《深入理解 Android 卷 III》 中 深入理解状态栏一章中的读书笔记。
SystemUI 在源码中的位置 frameworks/base/packages/SystemUI 中。
一、初识 SystemUI
主要讲状态栏和导航栏,它们都运行在 SystemUIService 中
1、SystemUIService 启动过程
在负责启动系统服务的 ServerThread 中,调用
ActivityManagerService.self().systemReady(new Runnable() {
public void run() {
...
if (!headless) startSystemUi(contextF);
然后启动 SystemUIService
static final void startSystemUi(Context context) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.OWNER);
}
/**
* The class names of the stuff to start.
*/
final Object[] SERVICES = new Object[] {
0, // system bar or status bar, filled in below.
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
com.android.systemui.settings.SettingsUI.class,
};
在 SystemUI 中,分离方案实现者是 PhoneStatusBar, 而集成布局方案的实现者则是 TabletStatusBar. 二者的本质功能是一致的,即提供虚拟按键、显示通知信息等,区别仅在与布局不同、以及由此所衍生的定制行为而已。
屏幕换的在 720 dp 以内时,使用分离的布局方案,判断条件在 PhoneWindowManager.setInitialDisplaySize() 中。
二、状态栏的创建
状态栏和导航栏的启动都是用 PhoneStatusBar.start() 完成的。
1、创建过程
在 PhoneStatuBar.addStatusBarWindow() 中
private void addStatusBarWindow() {
// Put up the view
// 状态栏的高度,默认是 25dp, 位置在 frameworks/base/core/res/res/values/dimen.xml 中
// R.dimen.status_bar_height
final int height = getStatusBarHeight();
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
height,
WindowManager.LayoutParams.TYPE_STATUS_BAR, // 窗口类型
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE // 状态栏不接受按键事件
// 状态栏接受导致设备唤醒的事件
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
// 允许状态栏支持触摸事件序列的拆分
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.TRANSLUCENT); // 状态栏的 Surface 像素格式为支持透明度
// 启动硬件加速
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
lp.gravity = getStatusBarGravity();
lp.setTitle("StatusBar");
lp.packageName = mContext.getPackageName();
// 创建 StatusBar 和 导航栏
makeStatusBarView();
// 添加到窗口,创建过程完成
mWindowManager.addView(mStatusBarWindow, lp);
}
2. 布局
在 makeStatusBarView() 方法中,布局文件是 R.layout.super_status_bar.xml