Android 7.0 SystemUI 之启动和状态栏和导航栏简介

一、SystemUI 是什么

首先SystemUI 是一个系统应用,apk路径位于/system/priv-app

源码路径位于:/framework/base/packages/SystemUI

它负责的功能如下:

  • 状态栏信息的展示:比如电量信息,时间,wifi状态等
  • 通知栏消息
  • 壁纸管理
  • 截图功能
  • 近期任务栏显示,比如长按home键显示最近使用的app
  • 录制屏幕功能
  • 截图服务

以下是7.0 SystemUI 的代码截图


二、SystemUI 的启动

SystemUI 是在SystemServer里的AMS实例的systemReady方法里调用startSystemUi方法启动

SystemServer路径:/base/services/java/com/android/server/SystemServer.java

mActivityManagerService.systemReady(new Runnable() {......static final void startSystemUi(Context context) {Intent intent = new Intent();intent.setComponent(new ComponentName("com.android.systemui","com.android.systemui.SystemUIService"));intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);//Slog.d(TAG, "Starting service: " + intent);context.startServiceAsUser(intent, UserHandle.SYSTEM);}......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这个方法里启动一个SystemUIService服务.

public class SystemUIService extends Service {@Overridepublic void onCreate() {super.onCreate();((SystemUIApplication) getApplication()).startServicesIfNeeded();}......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在onCreate方法中会调用SystemUIApplication的startServicesIfNeeded方法,这个方法会调用 startServicesIfNeeded(SERVICES)方法启动一系列服务(并不是真正的服务,都继承自SystemUI),可以这么说SystemUI就是一个容器,里面装有负责不同功能的模块。

public class SystemUIApplication extends Application {......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,Divider.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,com.android.systemui.keyboard.KeyboardUI.class,com.android.systemui.tv.pip.PipUI.class,com.android.systemui.shortcut.ShortcutKeyDispatcher.class};public void startServicesIfNeeded() {startServicesIfNeeded(SERVICES);}......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

startServicesIfNeeded方法会遍历services这个数组,依次调用service的start方法启动服务


private void startServicesIfNeeded(Class<?>[] services) {//如果已经启动了就返回if (mServicesStarted) {return;}//如果没启动完成完成if (!mBootCompleted) {if ("1".equals(SystemProperties.get("sys.boot_completed"))) {mBootCompleted = true;if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");}}final int N = services.length;for (int i=0; i<N; i++) {Class<?> cl = services[i];if (DEBUG) Log.d(TAG, "loading: " + cl);try {Object newService = SystemUIFactory.getInstance().createInstance(cl);mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);} catch (IllegalAccessException ex) {throw new RuntimeException(ex);} catch (InstantiationException ex) {throw new RuntimeException(ex);}//启动服务      mServices[i].start();//如果启动完成了if (mBootCompleted) {mServices[i].onBootCompleted();}}mServicesStarted = true;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

这里以com.android.systemui.statusbar.SystemBars.class为例,讲解一下


三、状态栏和导航栏 的启动

SystemBars的start方法会创建一个ServiceMonitor(服务监听者),会进入到ServiceMonitor的start方法

 public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {......public void 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}......   }   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在ServiceMonitor的start方法启动

  public class ServiceMonitor {......    public void start() {......mHandler.sendEmptyMessage(MSG_START_SERVICE);}......    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在Handler里处理这个MSG_START_SERVICE

  public class ServiceMonitor {......    private final Handler mHandler = new Handler() {public void handleMessage(Message msg) {switch(msg.what) {case MSG_START_SERVICE://启动服务startService();break;case MSG_CONTINUE_START_SERVICE:continueStartService();break;case MSG_STOP_SERVICE:stopService();break;case MSG_PACKAGE_INTENT:packageIntent((Intent)msg.obj);break;case MSG_CHECK_BOUND:checkBound();break;case MSG_SERVICE_DISCONNECTED:serviceDisconnected((ComponentName)msg.obj);break;}}};......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

startService方法如下


 public class ServiceMonitor {......    private void startService() {//获取服务组件名称mServiceName = getComponentNameFromSetting();//如果为空,回调服务的onNoService方法if (mServiceName == null) {mBound = false;mCallbacks.onNoService();} else {//不为空,回调服务的的onServiceStartAttempt方法long delay = mCallbacks.onServiceStartAttempt();mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_START_SERVICE, delay);}}......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这里对mServiceName是否为空进行判断,总之无论如何它最终都会启动这个服务。

回调SystemBars的onNoService里创建StatusBar

   public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {......@Overridepublic void onNoService() {if (DEBUG) Log.d(TAG, "onNoService");//创建StatusBarcreateStatusBarFromConfig();  // fallback to using an in-process implementation}......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  private void createStatusBarFromConfig() {//config_statusBarComponent就是PhoneStatusBarfinal String clsName = mContext.getString(R.string.config_statusBarComponent);Class<?> cls = null;try {cls = mContext.getClassLoader().loadClass(clsName);} catch (Throwable t) {throw andLog("Error loading status bar component: " + clsName, t);}try {//创建BaseStatusBar实例mStatusBar = (BaseStatusBar) cls.newInstance();} catch (Throwable t) {throw andLog("Error creating status bar component: " + clsName, t);}mStatusBar.mContext = mContext;mStatusBar.mComponents = mComponents;//启动mStatusBar.start();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在createStatusBarFromConfig方法里会获取一个config_statusBarComponent的字符串值,这个值就是PhoneStatusBar的clasName

所以这里的mStatusBar是PhoneStatusBar实例,启动了PhoneStatusBar

PhoneStatusBar的start方法

public class PhoneStatusBar extends BaseStatusBar implements DemoMode, DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,HeadsUpManager.OnHeadsUpChangedListener {......public void start() {......//调用父类的start方法,在父类BaseStatusBar里调用createAndAddWindows方法// 3.1super.start(); // calls createAndAddWindows()......//添加导航栏// 3.2addNavigationBar();......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

它会回调父类BaseStatusBar 的start方法

3.1、 super.start()

public abstract class BaseStatusBar extends SystemUI implementsCommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,ExpandableNotificationRow.OnExpandClickListener,OnGutsClosedListener {  ......public void start() {....../*实例化IStatusBarService,随后BaseStatusBar将自己注册到IStatusBarService之中。以此声明本实例才是状态栏的真正实现者,IStatusBarService会将其所接受到的请求转发给本实例。IStatusBarService会保存SystemUi的状态信息,避免SystemUi崩溃而造成信息的丢失*/mBarService = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));......//IStatusBarService与BaseStatusBar进行通信的桥梁。mCommandQueue = new CommandQueue(this);/*switches则存储了一些杂项:禁用功能列表,SystemUIVisiblity,是否在导航栏中显示虚拟的菜单键,输入法窗口是否可见、输入法窗口是否消费BACK键、是否接入了实体键盘、实体键盘是否被启用。*/int[] switches = new int[9];ArrayList<IBinder> binders = new ArrayList<IBinder>();/*它保存了用于显示在状态栏的系统状态区中的状态图标列表。在完成注册之后,IStatusBarService将会在其中填充两个数组,一个字符串数组用于表示状态的名称,一个StatusBarIcon类型的数组用于存储需要显示的图标资源。*/ArrayList<String> iconSlots = new ArrayList<>();ArrayList<StatusBarIcon> icons = new ArrayList<>();Rect fullscreenStackBounds = new Rect();Rect dockedStackBounds = new Rect();//IStatusBarService注册一些信息try {mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,fullscreenStackBounds, dockedStackBounds);} catch (RemoteException ex) {}//创建状态栏窗口createAndAddWindows();......}......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

BaseStatusBar进行一些设置,获取了IStatusBarService实例并注册一些信息到IStatusBarService中,IStatusBarService是一个系统服务,BaseStatusBar将自己注册到IStatusBarService之中,IStatusBarService会把操作状态栏和导航栏的请求转发给BaseStatusBar

为了保证SystemUI意外退出后不会发生信息丢失,IStatusBarService保存了所有需要状态栏与导航栏进行显示或处理的信息副本。 在注册时将一个继承自IStatusBar.Stub的CommandQueue的实例注册到IStatusBarService以建立通信,并将信息副本取回。

 public class CommandQueue extends IStatusBar.Stub {
  • 1

IStatusBarService的真身是StatusBarManagerService

路径:./services/core/java/com/android/server/statusbar/StatusBarManagerService.java

它的注册方法做一些数据的初始化

public class StatusBarManagerService extends IStatusBarService.Stub {......public void registerStatusBar(IStatusBar bar, List<String> iconSlots,List<StatusBarIcon> iconList, int switches[], List<IBinder> binders,Rect fullscreenStackBounds, Rect dockedStackBounds) {//检查权限   enforceStatusBarService();mBar = bar;synchronized (mIcons) {for (String slot : mIcons.keySet()) {iconSlots.add(slot);iconList.add(mIcons.get(slot));}}synchronized (mLock) {switches[0] = gatherDisableActionsLocked(mCurrentUserId, 1);switches[1] = mSystemUiVisibility;switches[2] = mMenuVisible ? 1 : 0;switches[3] = mImeWindowVis;switches[4] = mImeBackDisposition;switches[5] = mShowImeSwitcher ? 1 : 0;switches[6] = gatherDisableActionsLocked(mCurrentUserId, 2);switches[7] = mFullscreenStackSysUiVisibility;switches[8] = mDockedStackSysUiVisibility;binders.add(mImeToken);fullscreenStackBounds.set(mFullscreenStackBounds);dockedStackBounds.set(mDockedStackBounds);}}......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

这几者的关系如下

 
回到PhoneStatusBar中, 父类BaseStatusBar中的createAndAddWindows为抽象方法,由子类实现,看下PhoneStatusBar的 
createAndAddWindows

  @Overridepublic void createAndAddWindows() {//添加状态栏窗口addStatusBarWindow();}
  • 1
  • 2
  • 3
  • 4
  • 5

方法实现如下

  private void addStatusBarWindow() {//创建控件  makeStatusBarView();//创建StatusBarWindowManager实例    mStatusBarWindowManager = new StatusBarWindowManager(mContext);//创建远程输入控制实例    mRemoteInputController = new RemoteInputController(mStatusBarWindowManager,mHeadsUpManager);//添加状态栏窗口   mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

看下makeStatusBarView方法

makeStatusBarView的方法里调用 inflateStatusBarWindow(context)加载布局

 protected void inflateStatusBarWindow(Context context) {mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);}
  • 1
  • 2
  • 3

这里介绍下布局

状态栏布局介绍

整个状态栏的父布局是R.layout.super_status_bar,对应的是StatusBarWindowView这个自定义布局.


<com.android.systemui.statusbar.phone.StatusBarWindowView
    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:sysui="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true">......<!--正常状态栏下的布局 --><include layout="@layout/status_bar"android:layout_width="match_parent"android:layout_height="@dimen/status_bar_height" /><!--状态栏图标下的SeekBar布局 --><include layout="@layout/brightness_mirror" /><!--车载模式的布局  --><ViewStub android:id="@+id/fullscreen_user_switcher_stub"android:layout="@layout/car_fullscreen_user_switcher"android:layout_width="match_parent"android:layout_height="match_parent"/><!--状态栏下拉的布局  --><include layout="@layout/status_bar_expanded"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone" /></com.android.systemui.statusbar.phone.StatusBarWindowView>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

我这里以主要的布局层次做介绍,结合图片分析会更加清楚

StatusBarWindowView里有几个主要的布局

  • layout/status_bar
  • layout/brightness_mirror
  • layout/status_bar_expanded

如下图 


1.layout/status_bar

这个是正常状态下(未下拉的状态栏图标区域)

这个布局对应的是PhoneStatusBarView

<com.android.systemui.statusbar.phone.PhoneStatusBarView
    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"android:id="@+id/status_bar"android:background="@drawable/system_bar_background"android:orientation="vertical"android:focusable="false"android:descendantFocusability="afterDescendants">......<!--状态栏  --><LinearLayout android:id="@+id/status_bar_contents"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingStart="6dp"android:paddingEnd="8dp"android:orientation="horizontal"><!-- The alpha of this area is controlled from both PhoneStatusBarTransitions andPhoneStatusBar (DISABLE_NOTIFICATION_ICONS). --><!-- 通知图标区域--><com.android.systemui.statusbar.AlphaOptimizedFrameLayout
            android:id="@+id/notification_icon_area"android:layout_width="0dip"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal" /><!-- 系统图标区域 --><com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"android:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="horizontal"><!-- 系统图标 --><include layout="@layout/system_icons" /><!-- 时钟信息 --><com.android.systemui.statusbar.policy.Clock
                android:id="@+id/clock"android:textAppearance="@style/TextAppearance.StatusBar.Clock"android:layout_width="wrap_content"android:layout_height="match_parent"android:singleLine="true"android:paddingStart="@dimen/status_bar_clock_starting_padding"android:paddingEnd="@dimen/status_bar_clock_end_padding"android:gravity="center_vertical|start"/></com.android.keyguard.AlphaOptimizedLinearLayout></LinearLayout></com.android.systemui.statusbar.phone.PhoneStatusBarView>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

以下是细节图,连线表示层次结构


其中,状态栏的区域分为以下几种

  • 通知栏图标,在状态栏的最左侧显示通知信息,比如来了一个短信,那么就会弹出一个短信图标
  • 时间信息,显示一个时间,比如上午9:58
  • 信号图标,显示手机信号,wifi信号等
  • 电量图标,显示当前电量状态
  • 状态图标,wifi,蓝牙等开关状态

2.@layout/brightness_mirror

这个布局就是中间那个调整亮度的seekBar.没啥好介绍的.


3.@layout/status_bar_expanded

这个布局是下拉时的状态栏的布局

<com.android.systemui.statusbar.phone.NotificationPanelView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"android:id="@+id/notification_panel"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/transparent"><!--锁屏时的时钟布局  --><include
        layout="@layout/keyguard_status_view"android:layout_height="wrap_content"android:visibility="gone" /><com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
        android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="@integer/notification_panel_layout_gravity"android:id="@+id/notification_container_parent"android:clipToPadding="false"android:clipChildren="false"><!--quciksetting区域  --><com.android.systemui.AutoReinflateContainer
            android:id="@+id/qs_auto_reinflate_container"android:layout="@layout/qs_panel"android:layout_width="@dimen/notification_panel_width"android:layout_height="match_parent"android:layout_gravity="@integer/notification_panel_layout_gravity"android:clipToPadding="false"android:clipChildren="false" /><!-- 通知栏区域 --><com.android.systemui.statusbar.stack.NotificationStackScrollLayout
            android:id="@+id/notification_stack_scroller"android:layout_width="@dimen/notification_panel_width"android:layout_height="match_parent"android:layout_gravity="@integer/notification_panel_layout_gravity"android:layout_marginBottom="@dimen/close_handle_underlap" /><!--锁屏切换 --><ViewStub
            android:id="@+id/keyguard_user_switcher"android:layout="@layout/keyguard_user_switcher"android:layout_height="match_parent"android:layout_width="match_parent" /><!--锁屏下的状态栏 --><include
            layout="@layout/keyguard_status_bar"android:visibility="invisible" /></com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer><!--锁屏界面底部的图标 --><include
            layout="@layout/keyguard_bottom_area"android:visibility="gone" /></com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

细节图



创建完布局后,就会添加窗口到WindowManager里,这样状态栏就创建完成了.接下来会回到3.2 addNavigationBar()的步骤中.

3.2、addNavigationBar

这个方法是添加底部的导航栏的,就是那些home键,back键所在的区域.


public class PhoneStatusBar extends BaseStatusBar implements DemoMode, DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,HeadsUpManager.OnHeadsUpChangedListener {......protected void addNavigationBar() {if (mNavigationBarView == null) return;//初始化导航栏prepareNavigationBarView();//添加到WindowManager中mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());}......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这个方法里先初始化导航栏,然后把导航栏添加到窗口中.

prepareNavigationBarView()

public class PhoneStatusBar extends BaseStatusBar implements DemoMode, DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,HeadsUpManager.OnHeadsUpChangedListener {......private void prepareNavigationBarView() {//重新初始化 mNavigationBarView.reorient();//最近应用键ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();recentsButton.setOnClickListener(mRecentsClickListener);recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener);recentsButton.setLongClickable(true);recentsButton.setOnLongClickListener(mRecentsLongClickListener);//后退键ButtonDispatcher backButton = mNavigationBarView.getBackButton();backButton.setLongClickable(true);backButton.setOnLongClickListener(mLongPressBackListener);//home键ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();homeButton.setOnTouchListener(mHomeActionListener);homeButton.setOnLongClickListener(mLongPressHomeListener);//监听配置改变mAssistManager.onConfigurationChanged();}......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

四、结束

关于SystemUI的状态栏和导航栏就介绍完了,讲的很浅显,只是从整体上梳理了下流程.

原文地址: http://blog.csdn.net/qq_31530015/article/details/53507968

Android 7.0 SystemUI 之启动和状态栏和导航栏简介相关推荐

  1. 固定导航栏android,Android 状态栏和导航栏的真终极解决方案

    去年我写过一篇文章,透明状态栏和导航栏的终极解决方案,并在 Github 上开源了代码,https://github.com/Zackratos/UltimateBar,其实在那之后,我一直对这个项目 ...

  2. android 导航栏半透明,Android 沉浸式/透明式状态栏、导航栏

    前言 Android 从4.4开始引进透明状态栏和导航栏的概念,并且在5.0进行了改进,将透明变成了半透明的效果.虽然此特性最早出现在ios,但不否认效果还是很赞的. 至于4.4以下的手机,就不要考虑 ...

  3. Android 8.0 学习(26)---Android 8.0 SystemUI(一)

    Android 8.0 SystemUI(一):图文并茂的介绍 : 文章已同步更新至微信公众号:猿湿Xoong 我擅长什么? 当我想到这个这个问题的时候,脑子里是一片空白的:哎呀,我什么都知道点,可是 ...

  4. android 11.0 增加控制状态栏和导航栏的接口

    增加控制状态栏和导航栏的接口,代码如下 .../statusbar/NavigationBarController.java | 6 +-.../phone/NavigationBarFragment ...

  5. Android 7.0 SystemUI 状态/导航栏的隐藏与显示

    平台 Android 7.1 + RK3288 概述 从Android 4.4开始支持沉浸式全屏体验,在沉浸式全屏模式下,状态栏. 虚拟按键动态隐藏,应用可以使用完整的屏幕空间,按照 Google 的 ...

  6. android app启动流程分析,Android应用开发之Android 7.0 Launcher3的启动和加载流程分析...

    本文将带你了解Android应用开发Android 7.0 Launcher3的启动和加载流程分析,希望本文对大家学Android有所帮助. Android 7.0 Launcher3的启动和加载流程 ...

  7. Android 7.0 Launcher3的启动和加载流程分析----转载

     Android 7.0 Launcher3的启动和加载流程分析,Launcher的本质就是一个普通应用,它比普通应用多配置了Category的Android:name="android ...

  8. Android 5.0状态栏和导航栏

    Material Design推出之后,app中也開始沿用这样的风格 今天来说一下状态栏颜色设置,在4.4的时候推出了透明状态栏和导航栏.在不使用第三方库的情况下,4.4还是没有全然解决存在actio ...

  9. 深入分析Android 9.0源代码——Activity启动流程

    引言 点击此处查看<深入分析Android 9.0源代码>系列的组织结构和相关说明. 1 应用进程发起启动请求 本章的调用流程如下图所示: (Context) Activity Instr ...

最新文章

  1. (转)检测到在集成的托管管道模式下不适用的ASP.NET 设置
  2. 【工具篇】接口测试神器 -- Postman 入门教程
  3. 通过物理映射往虚拟机中传输数据
  4. tty,串口,控制台与驱动程序
  5. 【开源项目】EasyCmd命令图形化软件
  6. 从Pycharm说起
  7. protobuf windows lib链接库生成
  8. Python中yield的作用??
  9. 如何让ClickOnce进行手动更新(含代码)
  10. 经典前端框架,一个时代的落幕:如何看待layui 官网将于 2021年10月13日 进行下线?
  11. HTML 前端设置浏览器页签图标设置
  12. 代码提交到GitHub时出现的反复报错
  13. 索尼发布新Bravia液晶电视 84英寸4K分辨率!
  14. 永久免费的英文字体生成软件,例:
  15. java闭锁_Java并发工具类(闭锁CountDownLatch)
  16. 【转载】微服务架构论文-马丁福勒
  17. iOS开发关于block和局部变量和全局变量
  18. TiDB数据库架构——TiDB Server
  19. Java多线程编程模式实战指南一:Active Object模式(上)
  20. 关于人人都是产品经理

热门文章

  1. SharePoint 2013 Error - TypeError: Unable to get property 'replace' of undefined or null reference
  2. 通过 .htaccess 实现缓存策略
  3. Photoshop用户必知必会的28个快捷键
  4. YumRepo Error: All mirror URLs are not using问题解决
  5. IDE (Integrated Development Environment) 集成开发环境
  6. 【Python】一种超简单的变量交换方法
  7. Aria2 使用手札
  8. [Android] 检讨书生成器1.0
  9. 如何将.py文件转换为.exe
  10. Go进阶(8): map嵌套的两轮初始化