Android 9.0系统源码_SystemUI(二)系统状态栏导航栏的创建和添加

前言

上一篇我们具体分析了SystemUI的启动流程,在SystemServer的startOtherServices方法中,会启动SystemUIService服务,SystemUIService服务的onCreate方法会继续调用SystemUIApplication的startServicesIfNeeded方法,在该方法中会获取SystemUI组件各个类的具体路径,并通过反射创建对应的实例对象,然后依次调用每个组件的start() 方法启动相关类的服务,启动完成后,又会再次调用该组件的onBootCompleted( ) 方法。

framework/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java

    private void startServicesIfNeeded(String[] services) {
 		...
        mServices = new SystemUI[services.length];
        ...
        final int N = services.length;
        for (int i = 0; i < N; i++) {
            String clsName = services[i];//具体系统控件类的完整路径
        	...
            Class cls = Class.forName(clsName);
            mServices[i] = (SystemUI) cls.newInstance();//通过反射创建实例对象
            ...
            mServices[i].mContext = this;
            mServices[i].mComponents = mComponents;
            mServices[i].start(); //调用start()启动
			...
            if (mBootCompleted) {
                mServices[i].onBootCompleted(); //启动完毕,调用对应的onBootCompleted()方法
            }
        }
		...
        mServicesStarted = true;
    }

frameworks/base/packages/SystemUI/res/values/config.xml

    <string-array name="config_systemUIServiceComponents" translatable="false">
        <item>com.android.systemui.Dependency</item>
        <item>com.android.systemui.util.NotificationChannels</item>
        <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
        <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
        <item>com.android.systemui.recents.Recents</item>
        <item>com.android.systemui.volume.VolumeUI</item>
        <item>com.android.systemui.stackdivider.Divider</item>
        <item>com.android.systemui.SystemBars</item>
        <item>com.android.systemui.usb.StorageNotification</item>
        <item>com.android.systemui.power.PowerUI</item>
        <item>com.android.systemui.media.RingtonePlayer</item>
        <item>com.android.systemui.keyboard.KeyboardUI</item>
        <item>com.android.systemui.pip.PipUI</item>
        <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
        <item>@string/config_systemUIVendorServiceComponent</item>
        <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
        <item>com.android.systemui.LatencyTester</item>
        <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
        <item>com.android.systemui.ScreenDecorations</item>
        <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
        <item>com.android.systemui.SliceBroadcastRelayHandler</item>
    </string-array>

对这些 SystemUI服务 做一点介绍:

  • com.android.systemui.Dependency 是为了创建全局可用的依赖关系。
  • com.android.systemui.SystemBars创建整个SystemUI视图的入口类。
  • com.android.systemui.recents.Recents 最近任务
  • com.android.systemui.volume.VolumeUI 音量控制
  • com.android.systemui.pip.PipUI 画中画
  • com.android.systemui.statusbar.CommandQueue 是一个 Binder 类,它会被StatusBar注册到 StatusBarManagerService 中,用于接收StatusBarManagerService服务端的消息。

一、创建StatusBar

1、上面说过,SystemBars这个组件是整个SystemUI视图创建的入口类,它被启动时会调用 start() 方法,先看下该类的 start() 方法:

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemBars.java

public class SystemBars extends SystemUI {
 	...
    @Override
    public void start() {
        createStatusBarFromConfig();//通过配置创建系统状态栏
    }
    ...
   private void 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 = null;
      try {
          cls = mContext.getClassLoader().loadClass(clsName);//加载对应的类对象
      } catch (Throwable t) {
          throw andLog("Error loading status bar component: " + clsName, t);
      }
      try {
          mStatusBar = (SystemUI) cls.newInstance();//通过反射创建实例对象
      } catch (Throwable t) {
          throw andLog("Error creating status bar component: " + clsName, t);
      }
      mStatusBar.mContext = mContext;
      mStatusBar.mComponents = mComponents;
      mStatusBar.start();//调用系统状态栏的start方法
  }

从中可以知道,该方法中先读取 value/config.xml文件中config_statusBarComponent的值

<string name="config_statusBarComponent">com.android.systemui.statusbar.phone.StatusBar</string>

该数值其实就是状态栏所对应类的完整路径,然后再通过反射创建出具体的StatusBar对象实例,最后调用StatusBar的start()方法。

2、StatusBar的start方法如下所示。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
   
    protected StatusBarWindowView mStatusBarWindow;//状态栏视图容器 
    protected StatusBarWindowManager mStatusBarWindowManager;//状态栏窗口管理者

    @Override
    public void start() {
    	...
        createAndAddWindows(); //创建整个StatusBar视图并将其添加到Window中
        ...
    }
    ...
    public void createAndAddWindows() {
        addStatusBarWindow();
    }
    private void addStatusBarWindow() {
        makeStatusBarView(); //创建整个StatusBar视图
   		...
   		//调用StatusBarWindowManager的add方法,将视图添加到窗口
   		 mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());}
 	...
}

方法代码较多,这里我们只列出了几个关键点,首先是调用createAndAddWindows方法,该方法再调用addStatusBarWindow方法,addStatusBarWindow方法又会继续调用makeStatusBarView方法来构建系统状态栏视图,并将视图内容赋值给mStatusBarWindow,然后调用StatusBarWindowManager的add方法将状态栏视图添加到窗口上。

二、通过布局文件构建StatusBar所对应的视图

1、StatusBar的makeStatusBarView方法如下,该方法会继续调用inflateStatusBarWindow方法,将R.layout.super_status_bar布局文件构建成对应的视图。

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
    protected void makeStatusBarView() {
        final Context context = mContext;
        updateDisplaySize(); // populates mDisplayMetrics
        updateResources();
        updateTheme();
        //实例化整个statusBar视图,包括状态栏,通知面版,锁屏
        inflateStatusBarWindow(context);
        ...
    }
    
    protected void inflateStatusBarWindow(Context context) {
    	//实例化整个statusBar视图,包括状态栏,通知面版,锁屏
        mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);
    }
}    

2、布局super_status_bar.xmlz其实就是整个statusBar视图,它的的具体内容如下所示:

frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml

<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">

    <com.android.systemui.statusbar.BackDropView
            android:id="@+id/backdrop"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            sysui:ignoreRightInset="true"
            >
        <ImageView android:id="@+id/backdrop_back"
                   android:layout_width="match_parent"
                   android:scaleType="centerCrop"
                   android:layout_height="match_parent" />
        <ImageView android:id="@+id/backdrop_front"
                   android:layout_width="match_parent"
                   android:layout_height="match_parent"
                   android:scaleType="centerCrop"
                   android:visibility="invisible" />
    </com.android.systemui.statusbar.BackDropView>

    <com.android.systemui.statusbar.ScrimView
        android:id="@+id/scrim_behind"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:importantForAccessibility="no"
        sysui:ignoreRightInset="true"
        />
        
    <!--系统状态栏容器-->
    <FrameLayout
        android:id="@+id/status_bar_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

	<!--车载模式的布局  -->
    <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="invisible" />

	<!--状态栏图标下的SeekBar布局 -->
    <include layout="@layout/brightness_mirror" />

    <com.android.systemui.statusbar.ScrimView
        android:id="@+id/scrim_in_front"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:importantForAccessibility="no"
        sysui:ignoreRightInset="true"
        />

</com.android.systemui.statusbar.phone.StatusBarWindowView>

根视图StatusBarWindowView是一个FrameLayout,状态栏显示在最下面,然后通知面版会覆盖状态栏,最后还有一个底部视图在最上面。另外值得注意的一点就是id为status_bar_container的组件就是系统状态栏

三、系统状态栏所对应的布局文件

1、继续看StatusBar的makeStatusBarView方法,我们就会发现,id为status_bar_container所对应的Fragment其实就是状态栏,而它所对应的具体实现类就是CollapsedStatusBarFragment。

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
    protected void makeStatusBarView() {
        final Context context = mContext;
        updateDisplaySize();
        updateResources();
        updateTheme();
        //实例化整个SystemUI视图,包括状态栏,通知面版,锁屏
        inflateStatusBarWindow(context);
       	...
        // 创建状态栏视图
        FragmentHostManager.get(mStatusBarWindow)
                .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                    CollapsedStatusBarFragment statusBarFragment =
                            (CollapsedStatusBarFragment) fragment;
                    // 用通知图标控制器,初始化了通知图标区域和中心图标区域,并且显示出来
                    statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
                    mStatusBarView = (PhoneStatusBarView) fragment.getView();
                    mStatusBarView.setBar(this);
                    mStatusBarView.setPanel(mNotificationPanel);
                    mStatusBarView.setScrimController(mScrimController);
                    mStatusBarView.setBouncerShowing(mBouncerShowing);
                    if (mHeadsUpAppearanceController != null) {
                        // This view is being recreated, let's destroy the old one
                        mHeadsUpAppearanceController.destroy();
                    }
                    mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                            mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);
                    setAreThereNotifications();
                    checkBarModes();
                }).getFragmentManager()
                .beginTransaction()
                // CollapsedStatusBarFragment实现了状态栏的添加
                .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                        CollapsedStatusBarFragment.TAG)
                .commit();
       	...
     }
}     

可以看到CollapsedStatusBarFragment代表的就是状态栏视图,这个视图被添加到ID为status_bar_container的容器中。

2、接下来继续分析CollapsedStatusBarFragment的生命周期,即可知道状态栏的创建过程。这里创建视图的地方就在CollapsedStatusBarFragment的onCreateView方法中,该方法会将status_bar.xml布局文件转化为对应的视图。

public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
	...
	 @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            Bundle savedInstanceState) {
        //系统状态栏所对应的布局文件
        return inflater.inflate(R.layout.status_bar, container, false);
    }
	...
}

3、status_bar.xml 就是状态栏视图布局,该布局文件的具体内容如下所示:

frameworks/base/packages/SystemUI/res/layout/status_bar.xml

<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:layout_width="match_parent"
    android:layout_height="@dimen/status_bar_height"
    android:id="@+id/status_bar"
    android:background="@drawable/system_bar_background"
    android:orientation="vertical"
    android:focusable="false"
    android:descendantFocusability="afterDescendants"
    android:accessibilityPaneTitle="@string/status_bar">

    <ImageView
        android:id="@+id/notification_lights_out"
        android:layout_width="@dimen/status_bar_icon_size"
        android:layout_height="match_parent"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingBottom="2dip"
        android:src="@drawable/ic_sysbar_lights_out_dot_small"
        android:scaleType="center"
        android:visibility="gone"/>

	<!--状态栏  -->
    <LinearLayout android:id="@+id/status_bar_contents"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingEnd="@dimen/status_bar_padding_end"
        android:orientation="horizontal">
        
        <ViewStub
            android:id="@+id/operator_name"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout="@layout/operator_name" />
            
        <FrameLayout
            android:layout_height="match_parent"
            android:layout_width="0dp"
            android:layout_weight="1">

            <include layout="@layout/heads_up_status_bar_layout" />
            
          	<!--状态栏左边视图,依次显示运营商名字,时间,通知图标-->
            <LinearLayout
                android:id="@+id/status_bar_left_side"
                android:layout_height="match_parent"
                android:layout_width="match_parent"
                android:clipChildren="false">
                
                <!-- 时钟信息 -->
                <com.android.systemui.statusbar.policy.Clock
                    android:id="@+id/clock"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:textAppearance="@style/TextAppearance.StatusBar.Clock"
                    android:singleLine="true"
                    android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
                    android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
                    android:gravity="center_vertical|start"/>
                    
                <!--通知图标区域-->
                <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
                    android:id="@+id/notification_icon_area"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:orientation="horizontal"
                    android:clipChildren="false"/>

            </LinearLayout>
        </FrameLayout>

        <android.widget.Space
            android:id="@+id/cutout_space_view"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:gravity="center_horizontal|center_vertical"/>

        <!--系统图标区,由状态图标集和电池图标组成,状态图标集由wifi,bt等等组成-->
        <com.android.keyguard.AlphaOptimizedLinearLayout
            android:id="@+id/system_icon_area"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:gravity="center_vertical|end"
            >

            <include layout="@layout/system_icons" />
            
        </com.android.keyguard.AlphaOptimizedLinearLayout>
    </LinearLayout>

    <ViewStub
        android:id="@+id/emergency_cryptkeeper_text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout="@layout/emergency_cryptkeeper_text"/>

</com.android.systemui.statusbar.phone.PhoneStatusBarView>

从这个布局可以看出系统状态栏从左到右到底显示了什么。

  • 最左边的一块区域,依次显示运营商名字,时间,通知图标。
  • 中间一块区域。
  • 然后是最右边一块区域,显示的是状态图标(例如bt, wifi),以及电池图标。

四、将StatusBar视图内容到窗口上

1、继续往下看StatusBar的addStatusBarWindow方法。

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
   
    protected StatusBarWindowView mStatusBarWindow;//状态栏视图容器 
    protected StatusBarWindowManager mStatusBarWindowManager;//状态栏窗口管理者

    
    private void addStatusBarWindow() {
        makeStatusBarView(); //创建整个StatusBar视图
   		...
   		//调用StatusBarWindowManager的add方法,将StatusBar视图添加到窗口上
   		mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
    }
    
    protected void makeStatusBarView() {
        ...
        //实例化整个statusBar视图,包括状态栏,通知面版,锁屏
        inflateStatusBarWindow(context);
        ...
    }
    
    protected void inflateStatusBarWindow(Context context) {
    	//实例化整个statusBar视图,包括状态栏,通知面版,锁屏
        mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);
    }
}

在StatusBa调用makeStatusBarView创建状态栏视图容器之后,会调用StatusBarWindowManager的add方法将该视图容器添加到窗口上。

2、StatusBarWindowManager和add相关的代码如下所示。

public class StatusBarWindowManager implements RemoteInputController.Callback, Dumpable {
   
    private final WindowManager mWindowManager;
    
    public StatusBarWindowManager(Context context) {
        mContext = context;
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        ...代码省略...
    }

    public void add(View statusBarView, int barHeight) {
        mLp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                barHeight,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,//窗口类型为状态栏
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                PixelFormat.TRANSLUCENT);
        mLp.token = new Binder();
        mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        mLp.gravity = Gravity.TOP;
        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
        mLp.setTitle("StatusBar");//对用的Window的名称为StatusBar
        mLp.packageName = mContext.getPackageName();
        mStatusBarView = statusBarView;
        mBarHeight = barHeight;
        mWindowManager.addView(mStatusBarView, mLp);//将状态栏视图添加到WindowManager中
        mLpChanged = new WindowManager.LayoutParams();
        mLpChanged.copyFrom(mLp);
    }
    
}    

StatusBarWindowManager的构造方法首先获取WindowManager实例,然后创建调用WindowManager的add方法所需要的参数WindowManager.LayoutParams,结合源码可知状态栏所对应的窗口类型为WindowManager.LayoutParams.TYPE_STATUS_BAR,窗口名称为StatusBar。

五、创建导航栏视图内容并添加到窗口上

分析完了系统状态栏视图的创建和添加流程,我们再来分析一下系统导航栏视图的创建和添加流程。

1、系统导航栏的创建也是在StatusBar的makeStatusBarView方法中。

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
    
    protected IWindowManager mWindowManagerService;

    protected void makeStatusBarView() {
        ...
        try {
        	//判断是否存在导航栏
            boolean showNav = mWindowManagerService.hasNavigationBar();
            if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
            if (showNav) {
                createNavigationBar();
            }
        } catch (RemoteException ex) {
            // no window manager? good luck with that
        }
        ...
    }
    
    //创建导航栏视图
    protected void createNavigationBar() {
        mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> {
            mNavigationBar = (NavigationBarFragment) fragment;
            if (mLightBarController != null) {
                mNavigationBar.setLightBarController(mLightBarController);
            }
            mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility);
        });
    }
}

在创建完StatusBar所对应的视图之后,会调用IWindowManager的hasNavigationBar方法来判断系统是否存在导航栏,如果存在则会调用createNavigationBar方法,该方法会进一步调用NavigationBarFragment的静态方法create来创建导航栏视图。

2、NavigationBarFragment的create方法如下所示。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java

public class NavigationBarFragment extends Fragment implements Callbacks {

    public static View create(Context context, FragmentListener listener) {
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,//窗口类型为导航栏
                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
                PixelFormat.TRANSLUCENT);
        lp.token = new Binder();
        lp.setTitle("NavigationBar");//对用的Window的名称为NavigationBar
        lp.accessibilityTitle = context.getString(R.string.nav_bar);
        lp.windowAnimations = 0;

        View navigationBarView = LayoutInflater.from(context).inflate(
                R.layout.navigation_bar_window, null);

        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
        if (navigationBarView == null) return null;

        context.getSystemService(WindowManager.class).addView(navigationBarView, lp);//将导航栏视图添加到WindowManager中
        FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
        NavigationBarFragment fragment = new NavigationBarFragment();
        fragmentHost.getFragmentManager().beginTransaction()
                .replace(R.id.navigation_bar_frame, fragment, TAG)
                .commit();
        fragmentHost.addTagListener(TAG, listener);
        return navigationBarView;
    }
}

create方法首先创建调用WindowManager的add方法所需要的参数WindowManager.LayoutParams,结合源码可知导航栏所对应的窗口类型为WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,窗口名称为NavigationBar。

六、总结

状态栏和导航栏视图的创建和添加流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值