不小心把苹果手机设置id步骤的网络设置的PLMN里面的网络id给删了,怎么办,填回去是多少?

Android之SystemUI加载流程和NavigationBar的分析
本篇只分析SystemUI的加载过程和SystemUI的其中的一个模块StatusBar的小模块NavigationBar,以Android6.0代码进行分析
AndroidManifest.xml
SystemUIService
跟StatusBar相关的服务为SystemUIService,我们查看SystemUIService
public class SystemUIService extends Service {
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
//获取Application调用startServicesIfNeeded
public IBinder onBind(Intent intent) {
/*打印堆栈信息*/
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
if (args == null || args.length == 0) {
for (SystemUI ui: services) {
pw.println(&dumping service: & + ui.getClass().getName());
ui.dump(fd, pw, args);
String s = args[0];
for (SystemUI ui: services) {
String name = ui.getClass().getName();
if (name.endsWith(svc)) {
ui.dump(fd, pw, args);
分析SystemUIService代码,可以知道SystemUI主要做了两件事
获取Application对象加载SystemUI相关的类,这个等下分析SystemUIApplication代码可以知道 dump打印SystenUISerice运行过程中相关的堆栈信息
那么SystemUIService又是哪里开始启动的呢?竟然SystemUIService是个服务,那么启动服务要么就是startService
要么就是bindService进行启动,其启动方式则需要通过Intent来传入类名或者包名,因此在源码中搜索SystemUIService可以对比发现,它在
frameworks\base\services\java\com\android\server\SystemServer.java中进行启动
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);
在SystemServer的run方法中startOtherServices来启动SystemUIService服务,至于SystemServer则涉及到Android的启动流程,其大概流程为
int -& ServerManager -& Zygote -& SystemServer
SystemServer中会初始化一些Android的java层的服务,如ActivityManagerService、WindowManagerService等
这里SystemUI的加载过程就到此告一段落了,下面分析StatusBar的加载流程
上面讲到在SystemUIService的onCreate中获取SystemUIApplication对象来初始化SystemUI相关的类,这些类里面就包括了StatusBar相关的类,我们查看SystemUIApplication类
SystemUIApplication
public void onCreate() {
super.onCreate();
// Set the application theme that is inherited by all services. Note that setting the
// application theme in the manifest does only work for activities. Keep this in sync with
// the theme set there.
setTheme(R.style.systemui_theme);
//注释广播
IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
//开启直接返回
if (mBootCompleted)
if (DEBUG) Log.v(TAG, &BOOT_COMPLETED received&);
unregisterReceiver(this);
//标记启动
mBootCompleted =
//服务是否启动
if (mServicesStarted) {
final int N = mServices.
for (int i = 0; i & N; i++) {
//回调各服务的onBootCompleted函数
mServices[i].onBootCompleted();
}, filter);
在SystemUIApplication的onCreate中主要做了
设置主题(这个会影响其SystemUI的界面显示效果) 注册开机广播,设置标志位
startServicesIfNeeded
SystemUIService中的onCreate启动了这个方法,我们着重分析这个方法
public void startServicesIfNeeded() {
if (mServicesStarted) {
if (!mBootCompleted) {
// check to see if maybe it was already completed long before we began
// see ActivityManagerService.finishBooting()
//获取文件中的sys.boot_completed的值
if (&1&.equals(SystemProperties.get(&sys.boot_completed&))) {
mBootCompleted =
if (DEBUG) Log.v(TAG, &BOOT_COMPLETED was already sent&);
Log.v(TAG, &Starting SystemUI services.&);
final int N = SERVICES.
for (int i=0; i cl = SERVICES[i];
if (DEBUG) Log.d(TAG, &loading: & + cl);
//实例化各个类实例,放入mServices数组中
mServices[i] = (SystemUI)cl.newInstance();
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
mServices[i].mContext =
mServices[i].mComponents = mC
if (DEBUG) Log.d(TAG, &running: & + mServices[i]);
mServices[i].start();
if (mBootCompleted) {
mServices[i].onBootCompleted();
//服务启动标志
mServicesStarted =
这个方法中,首先判断mServicesStarted标志为来判断SystemUI相关的服务是否启动,同时根据系统配置文件来检查ActivityManagerService是否finishBooting,然后通过类加载机制来初始化SERVICES数组里面相关的类加入mServices中,然后start
* The classes of the stuff to start.
private final Class[] SERVICES = new Class[] {
com.android.systemui.tuner.TunerService.class,//定制状态栏服务
com.android.systemui.keyguard.KeyguardViewMediator.class,//锁屏相关
com.android.systemui.recents.Recents.class,//近期任务
com.android.systemui.volume.VolumeUI.class,//音量条
com.android.systemui.statusbar.SystemBars.class,//状态栏
com.android.systemui.usb.StorageNotification.class,//通知栏
com.android.systemui.power.PowerUI.class,//电源相关
com.android.systemui.media.RingtonePlayer.class,//铃声播放相关
* Hold a reference on the stuff we start.
private final SystemUI[] mServices = new SystemUI[SERVICES.length];
从mServices和SERVICES的定义可以发现SERVICES是一组包含全路径的相关的类,这些类包含一些我们常见的TunerService(定制状态栏服务)、
KeyguardViewMediator(锁屏相关)、Recents(近期任务)、VolumeUI(音量条)、SystemBars(状态栏)、StorageNotification(通知栏)、PowerUI(电源相关)、RingtonePlayer(铃声播放相关)类,它们都是继承与SystemUI抽象类,现在只分析StatusBar相关的SystemBars类
SystemBars
public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
private static final String TAG = &SystemBars&;
private static final boolean DEBUG =
private static final int WAIT_FOR_BARS_TO_DIE = 500;
// manages the implementation coming from the remote process
private ServiceMonitor mServiceM
// in-process fallback implementation, per the product config
private BaseStatusBar mStatusB
public void start() {
if (DEBUG) Log.d(TAG, &start&);
//实例化ServiceMonitor
mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
mServiceMonitor.start();
// will call onNoService if no remote service is found
/*服务没启动时,ServiceMonitor会回调onNoService*/
public void onNoService() {
if (DEBUG) Log.d(TAG, &onNoService&);
createStatusBarFromConfig();
// fallback to using an in-process implementation
/*服务已经启动的回调*/
public long onServiceStartAttempt() {
if (DEBUG) Log.d(TAG, &onServiceStartAttempt mStatusBar=&+mStatusBar);
if (mStatusBar != null) {
// tear down the in-process version, we'll recreate it again if needed
mStatusBar.destroy();
mStatusBar =
return WAIT_FOR_BARS_TO_DIE;
/*系统配置改变*/
protected void onConfigurationChanged(Configuration newConfig) {
if (mStatusBar != null) {
mStatusBar.onConfigurationChanged(newConfig);
/*打印堆栈*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mStatusBar != null) {
mStatusBar.dump(fd, pw, args);
/*从xml文件中获取PhoneStatusBar全路径,通过类加载器实例化类,调用其start*/
private void createStatusBarFromConfig() {
if (DEBUG) Log.d(TAG, &createStatusBarFromConfig&);
final String clsName = mContext.getString(R.string.config_statusBarComponent);
if (clsName == null || clsName.length() == 0) {
throw andLog(&No status bar component configured&, null);
Class cls =
cls = mContext.getClassLoader().loadClass(clsName);
} catch (Throwable t) {
throw andLog(&Error loading status bar component: & + clsName, t);
mStatusBar = (BaseStatusBar) cls.newInstance();
} catch (Throwable t) {
throw andLog(&Error creating status bar component: & + clsName, t);
mStatusBar.mContext = mC
mStatusBar.mComponents = mC
mStatusBar.start();
if (DEBUG) Log.d(TAG, &started & + mStatusBar.getClass().getSimpleName());
private RuntimeException andLog(String msg, Throwable t) {
Log.w(TAG, msg, t);
throw new RuntimeException(msg, t);
我们先从start方法开始分析
public void start() {
if (DEBUG) Log.d(TAG, &start&);
mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
mServiceMonitor.start();
// will call onNoService if no remote service is found
这里实例化ServiceMonitor类start,继续分析ServiceMonitor
ServiceMonitor
public ServiceMonitor(String ownerTag, boolean debug,
Context context, String settingKey, Callbacks callbacks) {
mTag = ownerTag + &.ServiceMonitor&;
mContext =
mSettingKey = settingK // Settings.Secure.BAR_SERVICE_COMPONENT
mCallbacks =
public void start() {
// listen for setting changes
/*Settings.Secure.BAR_SERVICE_COMPONENT改变时回调*/
ContentResolver cr = mContext.getContentResolver();
cr.registerContentObserver(Settings.Secure.getUriFor(mSettingKey),
false /*notifyForDescendents*/, mSettingObserver, UserHandle.USER_ALL);
// listen for package/component changes
//应用安装,改变,卸载会触发mBroadcastReceiver广播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme(&package&);
mContext.registerReceiver(mBroadcastReceiver, filter);
mHandler.sendEmptyMessage(MSG_START_SERVICE);
ServiceMOnitor是一个监听Settings.Secure.BAR_SERVICE_COMPONENT是否改变的类,在start中通过监听系统系统时应用的变化来启动服务
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String pkg = intent.getData().getSchemeSpecificPart();
if (mServiceName != null && mServiceName.getPackageName().equals(pkg)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_PACKAGE_INTENT, intent));
应用装载时,通过Handler发送MSG_PACKAGE_INTENT消息事件,我们查看Handler消息回调
// internal handler + messages used to serialize access to internal state
public static final int MSG_START_SERVICE = 1; //启动服务,并非真正启动,会根据ServiceName进行判断
public static final int MSG_CONTINUE_START_SERVICE = 2; //启动服务
public static final int MSG_STOP_SERVICE = 3;//停止服务消息
public static final int MSG_PACKAGE_INTENT = 4;//包安装事件消息
public static final int MSG_CHECK_BOUND = 5;//包改变或者卸载时,重新启动服务消息
public static final int MSG_SERVICE_DISCONNECTED = 6;//服务断开消息
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_START_SERVICE:
startService();
case MSG_CONTINUE_START_SERVICE:
continueStartService();
case MSG_STOP_SERVICE:
stopService();
case MSG_PACKAGE_INTENT:
packageIntent((Intent)msg.obj);
case MSG_CHECK_BOUND:
checkBound();
case MSG_SERVICE_DISCONNECTED:
serviceDisconnected((ComponentName)msg.obj);
private void packageIntent(Intent intent) {
if (mDebug) Log.d(mTag, &packageIntent intent=& + intent
+ & extras=& + bundleToString(intent.getExtras()));
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
mHandler.sendEmptyMessage(MSG_START_SERVICE);//发送启动服务消息
} else if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
final PackageManager pm = mContext.getPackageManager();
final boolean serviceEnabled = isPackageAvailable()
&& pm.getApplicationEnabledSetting(mServiceName.getPackageName())
!= PackageManager.COMPONENT_ENABLED_STATE_DISABLED
&& pm.getComponentEnabledSetting(mServiceName)
!= PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
if (mBound && !serviceEnabled) {
stopService();
scheduleCheckBound();
} else if (!mBound && serviceEnabled) {
startService();
当我们SystemUI应用检测到有新应用装载时,会发送MSG_START_SERVICE消息来启动服务,我们接着分析Handler的回调MSG_START_SERVICE消息
private void startService() {
mServiceName = getComponentNameFromSetting();
if (mDebug) Log.d(mTag, &startService mServiceName=& + mServiceName);
if (mServiceName == null) {
mCallbacks.onNoService();
long delay = mCallbacks.onServiceStartAttempt();
mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_START_SERVICE, delay);
/*从ContentProvider中取得包名*/
private ComponentName getComponentNameFromSetting() {
String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
mSettingKey, UserHandle.USER_CURRENT);
return cn == null ? null : ComponentName.unflattenFromString(cn);
首先从ContentProvider数据库中取得包名,如果没有启动,则回调CallBaback的onNoService服务,否则发送MSG_CONTINUE_START_SERVICE消息启动服务
private void continueStartService() {
if (mDebug) Log.d(mTag, &continueStartService&);
Intent intent = new Intent().setComponent(mServiceName);
mServiceConnection = new SC();
mBound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
if (mDebug) Log.d(mTag, &mBound: & + mBound);
} catch (Throwable t) {
Log.w(mTag, &Error binding to service: & + mServiceName, t);
if (!mBound) {
mCallbacks.onNoService();
至此可以知道,当远程服务没有启动时,会回调SystemBar的onNoService函数,我们回到SystemBar,分析onNoService函数
public void onNoService() {
if (DEBUG) Log.d(TAG, &onNoService&);
createStatusBarFromConfig();
// fallback to using an in-process implementation
private void createStatusBarFromConfig() {
if (DEBUG) Log.d(TAG, &createStatusBarFromConfig&);
final String clsName = mContext.getString(R.string.config_statusBarComponent);//从xml文件读取类名
if (clsName == null || clsName.length() == 0) {
throw andLog(&No status bar component configured&, null);
//通过类加载器实例化类
Class cls =
cls = mContext.getClassLoader().loadClass(clsName);
} catch (Throwable t) {
throw andLog(&Error loading status bar component: & + clsName, t);
mStatusBar = (BaseStatusBar) cls.newInstance();
} catch (Throwable t) {
throw andLog(&Error creating status bar component: & + clsName, t);
mStatusBar.mContext = mC
mStatusBar.mComponents = mC
mStatusBar.start();//调用类的start方法
if (DEBUG) Log.d(TAG, &started & + mStatusBar.getClass().getSimpleName());
上面分析可以得知,当远程服务没有启动时,首先从xml文件读取要启动的类名,我们来查看这个xml文件
res\values\config.xml
com.android.systemui.statusbar.phone.PhoneStatusBar
从上面可以知道,最终程序会加载PhoneStatusBar这个类,接下来分析PhoneStatusBar
PhoneStatusBar
首先我们从上面分析得知,当实例化PhoneStatusBar类后会调用start方法,我们就从PhoneStatusBar的start方法开始分析
public void start() {
//获取WindowManager,初始化当前显示界面大小
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
updateDisplaySize();
//src绘图模式
mScrimSrcModeEnabled = mContext.getResources().getBoolean(
R.bool.config_status_bar_scrim_behind_use_src);
//调用父类start方法
super.start(); // calls createAndAddWindows()
//MediaSession相关
mMediaSessionManager
= (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
// TODO: use MediaSessionManager.SessionListener to hook us up to future updates
// in session state
//添加导航栏
addNavigationBar();
// Lastly, call to the icon policy to install/update all the icons.
//更新状态栏图标
mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController,
mUserInfoController, mBluetoothController);
mIconPolicy.setCurrentUserSetup(mUserSetup);
mSettingsObserver.onChange(false); // set up
mHeadsUpObserver.onChange(true); // set up
if (ENABLE_HEADS_UP) {
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true,
mHeadsUpObserver);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
mHeadsUpObserver);
mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
mUnlockMethodCache.addListener(this);
startKeyguard();
mDozeServiceHost = new DozeServiceHost();
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mDozeServiceHost);
putComponent(DozeHost.class, mDozeServiceHost);
putComponent(PhoneStatusBar.class, this);
/// M:add for multi window @{
if(MultiWindowProxy.isSupported()) {
registerMroxyAgain();
setControllerUsers();
notifyUserAboutHiddenNotifications();
mScreenPinningRequest = new ScreenPinningRequest(mContext);
我们接着分析PhoneStatusBar父类的BaseStatusBar的start方法
BaseStatusBar
public void start() {
//获取Dispaly
mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
mDisplay = mWindowManager.getDefaultDisplay();
mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
mNotificationColorUtil = NotificationColorUtil.getInstance(mContext);
mNotificationData = new NotificationData(this);
mAccessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.checkService(DreamService.DREAM_SERVICE));
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
//监听设置文件的改变,以便更新ContenProvider数据库
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
mSettingsObserver);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
mSettingsObserver);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
mSettingsObserver,
UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
mLockscreenSettingsObserver,
UserHandle.USER_ALL);
//加载startbarService服务
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
//设置近期任务回调
mRecents = getComponent(Recents.class);
mRecents.setCallback(this);
//获取本地配置
final Configuration currentConfig = mContext.getResources().getConfiguration();
mLocale = currentConfig.
mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
mFontScale = currentConfig.fontS
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
//加载动画
mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.linear_out_slow_in);
mFastOutLinearIn = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.fast_out_linear_in);
// Connect in to the status bar manager service
StatusBarIconList iconList = new StatusBarIconList();
mCommandQueue = new CommandQueue(this, iconList);
int[] switches = new int[8];
ArrayList binders = new ArrayList();
mBarService.registerStatusBar(mCommandQueue, iconList, switches, binders);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
//调用createAndAddWindows方法
createAndAddWindows();
mSettingsObserver.onChange(false); // set up
disable(switches[0], switches[6], false /* animate */);
setSystemUiVisibility(switches[1], 0xffffffff);
topAppWindowChanged(switches[2] != 0);
// StatusBarManagerService has a back up of IME token and it's restored here.
setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0);
// Set up the initial icon state
int N = iconList.size();
int viewIndex = 0;
for (int i=0; i&n; i++)=&& {=&& statusbaricon=&& icon=&iconList.getIcon(i);& if=&& (icon=&& !=&null)& addicon(iconlist.getslot(i),=&& i,=&& viewindex,=&& icon);=&& viewindex++;=&& }=&& set=&& up=&& the=&& initial=&& notification=&& state.=&& try=&& mnotificationlistener.registerassystemservice(mcontext,=&& new=&& componentname(mcontext.getpackagename(),=&& getclass().getcanonicalname()),=&& userhandle.user_all);=&& catch=&& (remoteexception=&& e)=&& log.e(tag,=&& &unable=&& to=&& register=&& listener&,=&& e);=&& (debug)=&& log.d(tag,=&& string.format(=&& &init:=&& icons=&%d& disabled=&0x%08x& lights=&0x%08x& menu=&0x%08x& imebutton=&0x%08x&,& iconlist.size(),=&& switches[0],=&& switches[1],=&& switches[2],=&& switches[3]=&& ));=&& mcurrentuserid=&ActivityManager.getCurrentUser();& setheadsupuser(mcurrentuserid);=&& intentfilter=&& filter=&new& intentfilter();=&& filter.addaction(intent.action_user_switched);=&& filter.addaction(intent.action_user_added);=&& filter.addaction(intent.action_user_present);=&& filter.addaction(banner_action_cancel);=&& filter.addaction(banner_action_setup);=&& mcontext.registerreceiver(mbroadcastreceiver,=&& filter);=&& allusersfilter=&new& allusersfilter.addaction(=&& devicepolicymanager.action_device_policy_manager_state_changed);=&& mcontext.registerreceiverasuser(mallusersreceiver,=&& userhandle.all,=&& allusersfilter,=&& null,=&& null);=&& updatecurrentprofilescache();=&& ...
BaseStatusBar关于StatusBar相关的最主要是调用了createAndAddWindows方法,我们看下这个方法的定义
* Create all windows necessary for the status bar (including navigation, overlay panels, etc)
* and add them to the window manager.
protected abstract void createAndAddWindows();
这是一个抽象方法,也就是说,它会回调到子类的createAndAddWindows的实现方法中,我们重新回到PhoneStatusBar中,找到createAndAddWindows的方法实现
createAndAddWindows
public void createAndAddWindows() {
addStatusBarWindow();
private void addStatusBarWindow() {
makeStatusBarView();//创建statusbar视图
mStatusBarWindowManager = new StatusBarWindowManager(mContext);
//通过StatusBarWindowManager类的add方法加载到Window窗体中
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
protected PhoneStatusBarView makeStatusBarView() {
final Context context = mC
//通过Resources更新显示大小和一些资源文件
Resources res = context.getResources();
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
//加载StartBarWindowView视图
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
mStatusBarWindow.setService(this);
//监听下拉事件
mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
checkUserAutohide(v, event);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mExpandedVisible) {
animateCollapsePanels();
return mStatusBarWindow.onTouchEvent(event);
mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
mStatusBarView.setBar(this);
PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
mStatusBarView.setPanelHolder(holder);
mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
M: setBackground in 512 low ram device
if (!ActivityManager.isHighEndGfx() && !FeatureOptions.LOW_RAM_SUPPORT) {
mStatusBarWindow.setBackground(null);
mNotificationPanel.setBackground(new FastColorDrawable(context.getColor(
R.color.notification_panel_solid_background)));
//状态栏通知
mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow);
mHeadsUpManager.setBar(this);
mHeadsUpManager.addListener(this);
mHeadsUpManager.addListener(mNotificationPanel);
mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
mNotificationData.setHeadsUpManager(mHeadsUpManager);
if (MULTIUSER_DEBUG) {
mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
R.id.header_debug_info);
mNotificationPanelDebugText.setVisibility(View.VISIBLE);
//是否显示导航栏
boolean showNav = mWindowManagerService.hasNavigationBar();
Log.v(TAG, &hasNavigationBar=& + showNav);
if (showNav) {
/// M: add for multi window @{
//加载导航栏布局
int layoutId = R.layout.navigation_
if(MultiWindowProxy.isSupported()) {
layoutId = R.layout.navigation_bar_float_
mNavigationBarView = (NavigationBarView) View.inflate(context,
/*R.layout.navigation_bar*/layoutId, null);
mNavigationBarView.setDisabledFlags(mDisabled1);
mNavigationBarView.setBar(this);
mNavigationBarView.setOnVerticalChangedListener(
new NavigationBarView.OnVerticalChangedListener() {
public void onVerticalChanged(boolean isVertical) {
if (mAssistManager != null) {
mAssistManager.onConfigurationChanged();
mNotificationPanel.setQsScrimEnabled(!isVertical);
//设置导航栏触摸事件
mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
checkUserAutohide(v, event);
} catch (RemoteException ex) {
// no window manager? good luck with that
mAssistManager = new AssistManager(this, context);
// figure out which pixel-format to use for the status bar.
mPixelFormat = PixelFormat.OPAQUE;
//下拉通知栏
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setPhoneStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setHeadsUpManager(mHeadsUpManager);
mGroupManager.setOnGroupChangeListener(mStackScroller);
mKeyguardIconOverflowContainer =
(NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
mKeyguardIconOverflowContainer.setOnActivatedListener(this);
mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
mStackScroller.setOverflowContainer(mKeyguardIconOverflowContainer);
SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_speed_bump, mStackScroller, false);
mStackScroller.setSpeedBumpView(speedBump);
mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_no_notifications, mStackScroller, false);
mStackScroller.setEmptyShadeView(mEmptyShadeView);
//下拉清除键
mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
mDismissView.setOnButtonClickListener(new View.OnClickListener() {
public void onClick(View v) {
MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES);
clearAllNotifications();
mStackScroller.setDismissView(mDismissView);
mExpandedContents = mStackS
mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);
mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim,
mScrimSrcModeEnabled);
mHeadsUpManager.addListener(mScrimController);
mStackScroller.setScrimController(mScrimController);
mScrimController.setBackDropView(mBackdrop);
mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context);
mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
mHeader.setActivityStarter(this);
//锁屏相关
mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
mKeyguardBottomArea.setAssistManager(mAssistManager);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
(KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text),
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
// set the inital view visibility
setAreThereNotifications();
//主要是控制一些系统图标,第三方图标等的显示和更新
mIconController = new StatusBarIconController(
mContext, mStatusBarView, mKeyguardStatusBar, this);
// Background thread for any controllers that need it.
mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
// Other icons
//位置控制
mLocationController = new LocationControllerImpl(mContext,
mHandlerThread.getLooper()); // will post a notification
mBatteryController = new BatteryController(mContext);
mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
public void onPowerSaveChanged() {
mHandler.post(mCheckBarModes);
if (mDozeServiceHost != null) {
mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
mHotspotController = new HotspotControllerImpl(mContext);
mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());
mSecurityController = new SecurityControllerImpl(mContext);
/// M: add extra tiles @{
// add HotKnot in quicksetting
if (SIMHelper.isMtkHotKnotSupport()) {
Log.d(TAG, &makeStatusBarView : HotKnotControllerImpl&);
mHotKnotController = new HotKnotControllerImpl(mContext);
mHotKnotController =
// add AudioProfile in quicksetting
if (SIMHelper.isMtkAudioProfilesSupport()) {
Log.d(TAG, &makeStatusBarView : AudioProfileControllerImpl&);
mAudioProfileController = new AudioProfileControllerImpl(mContext);
mAudioProfileController =
SIMHelper.setContext(mContext);
if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
mRotationLockController = new RotationLockControllerImpl(mContext);
mUserInfoController = new UserInfoController(mContext);
mVolumeComponent = getComponent(VolumeComponent.class);
if (mVolumeComponent != null) {
mZenModeController = mVolumeComponent.getZenController();
Log.d(TAG, &makeStatusBarView : CastControllerImpl +&);
mCastController = new CastControllerImpl(mContext);
Log.d(TAG, &makeStatusBarView : CastControllerImpl -&);
final SignalClusterView signalCluster =
(SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
final SignalClusterView signalClusterKeyguard =
(SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
final SignalClusterView signalClusterQs =
(SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
mNetworkController.addSignalCallback(signalCluster);
mNetworkController.addSignalCallback(signalClusterKeyguard);
mNetworkController.addSignalCallback(signalClusterQs);
signalCluster.setSecurityController(mSecurityController);
signalCluster.setNetworkController(mNetworkController);
signalClusterKeyguard.setSecurityController(mSecurityController);
signalClusterKeyguard.setNetworkController(mNetworkController);
signalClusterQs.setSecurityController(mSecurityController);
signalClusterQs.setNetworkController(mNetworkController);
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
if (isAPhone) {
mNetworkController.addEmergencyListener(mHeader);
/// M: Support &Operator plugin - Customize Carrier Label for PLMN& @{
mStatusBarPlmnPlugin = PluginFactory.getStatusBarPlmnPlugin(context);
if (supportCustomizeCarrierLabel()) {
mCustomizeCarrierLabel = mStatusBarPlmnPlugin.customizeCarrierLabel(
mNotificationPanel, null);
/// M: Support &Operator plugin - Customize Carrier Label for PLMN& @}
mFlashlightController = new FlashlightController(mContext);
mKeyguardBottomArea.setFlashlightController(mFlashlightController);
mKeyguardBottomArea.setPhoneStatusBar(this);
mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
mAccessibilityController = new AccessibilityController(mContext);
mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
mNextAlarmController = new NextAlarmController(mContext);
mKeyguardMonitor = new KeyguardMonitor(mContext);
if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {
mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
mHandler);
mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
(ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),
mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController);
// Set up the quick settings tile panel
mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
if (mQSPanel != null) {
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, mHotspotController,
mCastController, mFlashlightController,
mUserSwitcherController, mKeyguardMonitor,
mSecurityController,
/// M: add HotKnot in quicksetting
mHotKnotController,
/// M: add AudioProfile in quicksetting
mAudioProfileController
mQSPanel.setHost(qsh);
mQSPanel.setTiles(qsh.getTiles());
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
mHeader.setQSPanel(mQSPanel);
qsh.setCallback(new QSTileHost.Callback() {
public void onTilesChanged() {
mQSPanel.setTiles(qsh.getTiles());
// User info. Trigger first load.
mHeader.setUserInfoController(mUserInfoController);
mKeyguardStatusBar.setUserInfoController(mUserInfoController);
mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController);
mUserInfoController.reloadUserInfo();
mHeader.setBatteryController(mBatteryController);
((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
mBatteryController);
mKeyguardStatusBar.setBatteryController(mBatteryController);
mHeader.setNextAlarmController(mNextAlarmController);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBroadcastReceiver.onReceive(mContext,
new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
// receive broadcasts
//注册系统广播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
IntentFilter demoFilter = new IntentFilter();
if (DEBUG_MEDIA_FAKE_ARTWORK) {
demoFilter.addAction(ACTION_FAKE_ARTWORK);
demoFilter.addAction(ACTION_DEMO);
context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
android.Manifest.permission.DUMP, null);
// listen for USER_SETUP_COMPLETE setting (per-user)
resetUserSetupObserver();
// disable profiling bars, since they overlap and clutter the output on app windows
ThreadedRenderer.overrideProperty(&disableProfileBars&, &true&);
// Private API call to make the shadows look better for Recents
ThreadedRenderer.overrideProperty(&ambientRatio&, String.valueOf(1.5f));
mStatusBarPlmnPlugin.addPlmn((LinearLayout)mStatusBarView.
findViewById(R.id.status_bar_contents), mContext);
return mStatusBarV
因为这块涉及的太广,所以接下来只分析StatusBar相关的一块,以导航栏为例进行讲解,我们重新回到PhoneStatusBar的start方法中,找到导航栏这块,发现它是调用addNavigationBar函数,所以我们查看这个函数:
// For small-screen devices (read: phones) that lack hardware navigation buttons
private void addNavigationBar() {
if (DEBUG) Log.v(TAG, &addNavigationBar: about to add & + mNavigationBarView);
//1.判断mNavigationBarView是否为空,这个视图有上面分析的makeStatusBarView方法中进行创建
if (mNavigationBarView == null)
//2.加载导航栏的具体显示(导航栏的显示由横向显示和竖向显示,后面分析)
prepareNavigationBarView();
//3.根据LayoutParams,加载导航栏到窗体中
mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
//设置导航栏三个图标的点击事件
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
mNavigationBarView.getRecentsButton().setLongClickable(true);
mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);
mNavigationBarView.getBackButton().setLongClickable(true);
mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
mNavigationBarView.getHomeButton().setOnLongClickListener(mLongPressHomeListener);
mAssistManager.onConfigurationChanged();
/// M: add for multi window @{
if(MultiWindowProxy.isSupported()){
mNavigationBarView.getFloatButton().setOnClickListener(mFloatClickListener);
if(mIsSplitModeEnable){
mNavigationBarView.getFloatModeButton().setOnClickListener(mFloatModeClickListener);
mNavigationBarView.getSplitModeButton().setOnClickListener(mSplitModeClickListener);
MultiWindowProxy.getInstance().setSystemUiCallback(new MWSystemUiCallback());
我们根据上面的注释来进行分析,主要内容有
1. 导航栏布局的创建
2. 导航栏布局分析及加载
3. 导航栏LayoutParams分析
导航栏布局的创建
在PhoneStatusBar的makeStatusBarView方法中,我们可以看到导航栏是怎么创建的
protected PhoneStatusBarView makeStatusBarView() {
//是否显示导航栏
boolean showNav = mWindowManagerService.hasNavigationBar();
Log.v(TAG, &hasNavigationBar=& + showNav);
if (showNav) {
/// M: add for multi window @{
//加载导航栏布局
int layoutId = R.layout.navigation_
//是否支持多窗口
if(MultiWindowProxy.isSupported()) {
layoutId = R.layout.navigation_bar_float_
mNavigationBarView = (NavigationBarView) View.inflate(context,
/*R.layout.navigation_bar*/layoutId, null);
mNavigationBarView.setDisabledFlags(mDisabled1);
mNavigationBarView.setBar(this);
mNavigationBarView.setOnVerticalChangedListener(
new NavigationBarView.OnVerticalChangedListener() {
public void onVerticalChanged(boolean isVertical) {
if (mAssistManager != null) {
mAssistManager.onConfigurationChanged();
mNotificationPanel.setQsScrimEnabled(!isVertical);
//设置导航栏触摸事件
mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
checkUserAutohide(v, event);
} catch (RemoteException ex) {
// no window manager? good luck with that
首先由mWindowManagerService的hasNavigationBar来决定是否显示导航栏,同时通过加载navigation_bar(多窗口加载navigation_bar_float_window)布局来显示导航栏,我们来查看hasNavigationBar方法,因为mWidnwoManagerService是IWindowManagerService由PhoneWindowManager进行调用:
frameworks\base\service\core\java\com\android\server\PhoneWindowManager.java
PhoneWindowManager
// Use this instead of checking config_showNavigationBar so that it can be consistently
// overridden by qemu.hw.mainkeys in the emulator.
public boolean hasNavigationBar() {
return mHasNavigationB
mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
// Allow a system property to override this. Used by the emulator.
// See also hasNavigationBar().
String navBarOverride = SystemProperties.get(&qemu.hw.mainkeys&);
if (&1&.equals(navBarOverride)) {
mHasNavigationBar =
} else if (&0&.equals(navBarOverride)) {
mHasNavigationBar =
从framework\base\core\res\res\valuse\config.xml中获取mHashNavigationBar的值
然后从系统配置位置中取qemu.hw.mainkeys的值,所以这里给我们提供了一个隐藏状态栏的新思路,除了在createAndAddWindows中注释掉addNavigationBar函数外,我们也可以通过修改framework下的config.xml的config_showNavigationBar的值和修改系统配置文件的值来达到隐藏状态栏的目的
导航栏布局分析及加载
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
//设置导航栏三个图标的点击事件
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
mNavigationBarView.getRecentsButton().setLongClickable(true);
mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);
mNavigationBarView.getBackButton().setLongClickable(true);
mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
mNavigationBarView.getHomeButton().setOnLongClickListener(mLongPressHomeListener);
mAssistManager.onConfigurationChanged();
/// M: add for multi window @{
if(MultiWindowProxy.isSupported()){
mNavigationBarView.getFloatButton().setOnClickListener(mFloatClickListener);
if(mIsSplitModeEnable){
mNavigationBarView.getFloatModeButton().setOnClickListener(mFloatModeClickListener);
mNavigationBarView.getSplitModeButton().setOnClickListener(mSplitModeClickListener);
MultiWindowProxy.getInstance().setSystemUiCallback(new MWSystemUiCallback());
导航栏布局的确切显示在prepareNavigationBarView中的mNavigationBarView.reorient();来决定,我们查看reorient方法
public void reorient() {
//获取屏幕方向
final int rot = mDisplay.getRotation();
//隐藏导航栏布局
for (int i=0; i&4; i++) {
mRotatedViews[i].setVisibility(View.GONE);
//根据屏幕方向显示导航栏布局
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
setLayoutTransitionsEnabled(mLayoutTransitionsEnabled);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
// force the low profile & disabled states into compliance
mBarTransitions.init();
setDisabledFlags(mDisabledFlags, true /* force */);
setMenuVisibility(mShowMenu, true /* force */);
if (DEBUG) {
Log.d(TAG, &reorient(): rot=& + mDisplay.getRotation());
updateTaskSwitchHelper();
setNavigationIconHints(mNavigationIconHints, true);
导航栏的显示由屏幕的方向来决定,而导航栏有两种不同的显示方式,横向显示和竖向显示,我们可以从mRotatedViews进行追查到
View[] mRotatedViews = new View[4];
public void onFinishInflate() {
//屏幕方位0和180方向显示的导航栏为rot0
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
//屏幕访问90和270显示的导航栏为rot90
mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];
//mCurrentView = mRotatedViews[Surface.ROTATION_0];
mCurrentView = mRotatedViews[Surface.ROTATION_90];
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
updateRTLOrder();
布局加载完成后,会回调onFinishInflate方法,在这方法中对屏幕的几个方向初始化4个导航栏view,其中0和180为横向布局,90和270为纵向布局,我们可以从导航栏(NavigationBarView)布局文件中可以看出
res\layout\navigation_bar.xml和res\layout\navigation_bar
&framelayout android:id="@+id/rot0" android:layout_height="match_parent" android:layout_width="match_parent"&
&/framelayout&
&framelayout android:id="@+id/rot90" android:layout_height="match_parent" android:layout_width="match_parent" android:paddingtop="0dp" android:visibility="gone"&
&/framelayout&
所以说,当我们的需求为0或者90度方向,要想导航栏纵向显示,我们只需要修改成导航栏纵向布局即可,当然我们也可以按需求来隐藏某些导航栏按键(布局中设置某些控件为gone)
public void onFinishInflate() {
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];
//mCurrentView = mRotatedViews[Surface.ROTATION_0];
//显示纵向的导航栏
mCurrentView = mRotatedViews[Surface.ROTATION_90];
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
updateRTLOrder();
导航栏LayoutParams分析
我们回到PhoneStatusBar的addNavigationBar继续分析最后一个导航栏的LayoutParameters,它决定了导航栏在窗体上的显示位置
private WindowManager.LayoutParams getNavigationBarLayoutParams() {
//充满父布局
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,//导航栏
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING//当手机处于睡眠状态时,如果屏幕被按下,那么该window将第一个收到到事件
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE//不获取焦点
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL//即使在该window在可获得焦点情况下,仍然把该window之外的任何event发送到该window之后的其他window
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH//不接受事件,转发到其他window
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,//当该window在可以接受触摸屏情况下,让因在该window之外,而发送到后面的window的触摸屏可以支持split touch.
PixelFormat.TRANSLUCENT);
// this will allow the navbar to run in an overlay on devices that support this
if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;//硬件加速
//lp.gravity = Gravity.RIGHT;
lp.setTitle(&NavigationBar&);
lp.windowAnimations = 0;
上面的LayoutParames决定了导航栏在窗体的大小(受父布局影响)和显示的位置效果,当我们的需求如果要把导航栏显示在屏幕的右边时,我们可以在上面代码中加上下面一句
lp.gravity = Gravity.RIGHT;
SystemUI包含了太多内容,本篇只是分析了SystemUI的加载流程,同时初步的分析了StatusBar中一个小模块NavigationBar,后续会针对SystemUI的其他模块进行分析。

我要回帖

更多关于 手机网络id怎么设置 的文章

 

随机推荐