博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android之SystemUI载入流程和NavigationBar的分析
阅读量:5304 次
发布时间:2019-06-14

本文共 51578 字,大约阅读时间需要 171 分钟。

Android之SystemUI载入流程和NavigationBar的分析

本篇仅仅分析SystemUI的载入过程和SystemUI的当中的一个模块StatusBar的小模块NavigationBar,以Android6.0代码进行分析

AndroidManifest.xml

SystemUIService

跟StatusBar相关的服务为SystemUIService,我们查看SystemUIService源代码

public class SystemUIService extends Service {    @Override    public void onCreate() {        super.onCreate();        ((SystemUIApplication) getApplication()).startServicesIfNeeded();        //获取Application调用startServicesIfNeeded    }    @Override    public IBinder onBind(Intent intent) {        return null;    }    /*打印堆栈信息*/    @Override    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);            }        } else {            String svc = 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

onCreate

@Overridepublic 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() {        @Override        public void onReceive(Context context, Intent intent) {            //开启直接返回            if (mBootCompleted) return;            if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");            unregisterReceiver(this);            //标记启动            mBootCompleted = true;            //服务是否启动            if (mServicesStarted) {                final int N = mServices.length;                for (int i = 0; i < N; i++) {                    //回调各服务的onBootCompleted函数                    mServices[i].onBootCompleted();                }            }        }    }, filter);}

在SystemUIApplication的onCreate中主要做了

  • 设置主题(这个会影响其SystemUI的界面显示效果)
  • 注冊开机广播。设置标志位

startServicesIfNeeded

SystemUIService中的onCreate启动了这种方法。我们着重分析这种方法

public void startServicesIfNeeded() {    if (mServicesStarted) {        return;    }    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 = true;            if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");        }    }    Log.v(TAG, "Starting SystemUI services.");    final int N = SERVICES.length;    for (int i=0; i

> cl = SERVICES[i]; if (DEBUG) Log.d(TAG, "loading: " + cl); //实例化各个类实例,放入mServices数组中 try { mServices[i] = (SystemUI)cl.newInstance(); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } mServices[i].mContext = this; mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); mServices[i].start(); if (mBootCompleted) { mServices[i].onBootCompleted(); } } //服务启动标志 mServicesStarted = true; }

这种方法中,首先推断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 = false;    private static final int WAIT_FOR_BARS_TO_DIE = 500;    // manages the implementation coming from the remote process    private ServiceMonitor mServiceMonitor;    // in-process fallback implementation, per the product config    private BaseStatusBar mStatusBar;    @Override    public void start() {        if (DEBUG) Log.d(TAG, "start");        //实例化ServiceMonitor        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);        //start        mServiceMonitor.start();  // will call onNoService if no remote service is found    }    /*服务没启动时。ServiceMonitor会回调onNoService*/    @Override    public void onNoService() {        if (DEBUG) Log.d(TAG, "onNoService");        createStatusBarFromConfig();  // fallback to using an in-process implementation    }    /*服务已经启动的回调*/    @Override    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 = null;            return WAIT_FOR_BARS_TO_DIE;        }        return 0;    }    /*系统配置改变*/    @Override    protected void onConfigurationChanged(Configuration newConfig) {        if (mStatusBar != null) {            mStatusBar.onConfigurationChanged(newConfig);        }    }    /*打印堆栈*/    @Override    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 = null; try { cls = mContext.getClassLoader().loadClass(clsName); } catch (Throwable t) { throw andLog("Error loading status bar component: " + clsName, t); } try { mStatusBar = (BaseStatusBar) cls.newInstance(); } catch (Throwable t) { throw andLog("Error creating status bar component: " + clsName, t); } mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; 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方法開始分析

@Override    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";        mDebug = debug;        mContext = context;        mSettingKey = settingKey; // Settings.Secure.BAR_SERVICE_COMPONENT        mCallbacks = callbacks;    }    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();                    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;            }        }    };    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) {            mBound = false;            mCallbacks.onNoService();        } else {            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);        try {            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函数

...     @Override        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 = null; try { cls = mContext.getClassLoader().loadClass(clsName); } catch (Throwable t) { throw andLog("Error loading status bar component: " + clsName, t); } try { mStatusBar = (BaseStatusBar) cls.newInstance(); } catch (Throwable t) { throw andLog("Error creating status bar component: " + clsName, t); } mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; 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方法開始分析

start

...    @Override    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()) {            registerMWProxyAgain();        }        /// @}        setControllerUsers();        notifyUserAboutHiddenNotifications();        mScreenPinningRequest = new ScreenPinningRequest(mContext);    }    ...

我们接着分析PhoneStatusBar父类的BaseStatusBar的start方法

BaseStatusBar

start

...    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),                true,                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.locale;        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);        mFontScale = currentConfig.fontScale;        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
(); try { 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

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

...    @Override    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 = mContext;        //通过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() {            @Override            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);        }        try {            //是否显示导航栏            boolean showNav = mWindowManagerService.hasNavigationBar();             Log.v(TAG, "hasNavigationBar=" + showNav);            if (showNav) {                /// M: add for multi window @{                //载入导航栏布局                int layoutId = R.layout.navigation_bar;                if(MultiWindowProxy.isSupported()) {                    layoutId = R.layout.navigation_bar_float_window;                }                mNavigationBarView = (NavigationBarView) View.inflate(context,                        /*R.layout.navigation_bar*/layoutId, null);                /// @}                mNavigationBarView.setDisabledFlags(mDisabled1);                mNavigationBarView.setBar(this);                mNavigationBarView.setOnVerticalChangedListener(                        new NavigationBarView.OnVerticalChangedListener() {                    @Override                    public void onVerticalChanged(boolean isVertical) {                        if (mAssistManager != null) {                            mAssistManager.onConfigurationChanged();                        }                        mNotificationPanel.setQsScrimEnabled(!isVertical);                    }                });                //设置导航栏触摸事件                mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {                    @Override                    public boolean onTouch(View v, MotionEvent event) {                        checkUserAutohide(v, event);                        return false;                    }});            }        } 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() {            @Override            public void onClick(View v) {                MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES);                clearAllNotifications();            }        });        mStackScroller.setDismissView(mDismissView);        mExpandedContents = mStackScroller;        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() {            @Override            public void onPowerSaveChanged() {                mHandler.post(mCheckBarModes);                if (mDozeServiceHost != null) {                    mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());                }            }            @Override            public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {                // noop            }        });        //网络        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);        } else {            mHotKnotController = null;        }        // add AudioProfile in quicksetting        if (SIMHelper.isMtkAudioProfilesSupport()) {            Log.d(TAG, "makeStatusBarView : AudioProfileControllerImpl");            mAudioProfileController = new AudioProfileControllerImpl(mContext);        } else {            mAudioProfileController = null;        }        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() {                @Override                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 mStatusBarView;    }    ...

由于这块涉及的太广。所以接下来仅仅分析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) return;        //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() {        ...        ...        try {            //是否显示导航栏            boolean showNav = mWindowManagerService.hasNavigationBar();             Log.v(TAG, "hasNavigationBar=" + showNav);            if (showNav) {                /// M: add for multi window @{                //载入导航栏布局                int layoutId = R.layout.navigation_bar;                //是否支持多窗口                if(MultiWindowProxy.isSupported()) {                    layoutId = R.layout.navigation_bar_float_window;                }                mNavigationBarView = (NavigationBarView) View.inflate(context,                        /*R.layout.navigation_bar*/layoutId, null);                /// @}                mNavigationBarView.setDisabledFlags(mDisabled1);                mNavigationBarView.setBar(this);                mNavigationBarView.setOnVerticalChangedListener(                        new NavigationBarView.OnVerticalChangedListener() {                    @Override                    public void onVerticalChanged(boolean isVertical) {                        if (mAssistManager != null) {                            mAssistManager.onConfigurationChanged();                        }                        mNotificationPanel.setQsScrimEnabled(!isVertical);                    }                });                //设置导航栏触摸事件                mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {                    @Override                    public boolean onTouch(View v, MotionEvent event) {                        checkUserAutohide(v, event);                        return false;                    }});            }        } 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.    @Override    public boolean hasNavigationBar() {        return mHasNavigationBar;    }    ...    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 = false;     } else if ("0".equals(navBarOverride)) {         mHasNavigationBar = true;    }    ...

从framework\base\core\res\res\valuse\config.xml中获取mHashNavigationBar的值

ture

然后从系统配置位置中取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方法

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];    ...    @Override    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

所以说,当我们的需求为0或者90度方向,要想导航栏纵向显示,我们仅仅须要改动成导航栏纵向布局就可以。当然我们也能够按需求来隐藏某些导航栏按键(布局中设置某些控件为gone)

@Override    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,//导航栏                    0                    | 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;        return lp;    }

上面的LayoutParames决定了导航栏在窗口的大小(受父布局影响)和显示的位置效果。当我们的需求假设要把导航栏显示在屏幕的右边时。我们能够在上面代码中加上以下一句

lp.gravity = Gravity.RIGHT;

SystemUI包括了太多内容,本篇仅仅是分析了SystemUI的载入流程。同一时候初步的分析了StatusBar中一个小模块NavigationBar,兴许会针对SystemUI的其它模块进行分析。

转载于:https://www.cnblogs.com/liguangsunls/p/7308864.html

你可能感兴趣的文章
Xamarin.Forms教程开发Xamarin.Forms应用程序需要的工具
查看>>
web测试——完结感言
查看>>
Linux系统内核驱动之位操作
查看>>
oracle 按每天,每周,每月,每季度,每年查询统计数据
查看>>
Laravel 5.2 教程 - 文件上传
查看>>
mysql最佳优化经验
查看>>
php代码在服务器中查看接值
查看>>
使用U盘代替光盘来刻录ISO镜像文件的方法
查看>>
Jmeter入门7 测试中使用到的几个定时器和逻辑控制器
查看>>
Basic View
查看>>
2018.09.08 NOIP模拟trip(最长链计数)
查看>>
互斥锁
查看>>
C# 读写ini配置文件的类
查看>>
测试php单例模式和静态访问,实例化访问的效率
查看>>
python的partial()用法说明
查看>>
创建自己的网上个性印章
查看>>
Android开发之文件保存读取
查看>>
python多线程的实现方法总结
查看>>
亲自打造Deferred对象
查看>>
改进后的socket轮子,欢迎挑战
查看>>