Android快速设置中添加隐藏状态栏和导航栏选项

Android的状态栏和导航栏是在SystemUI中实现的,目前还不支持手动隐藏和显示状态栏和导航栏,接下来我们将对此功能进行讲解。
在系统启动过程中,会加载SystemUI中的状态栏,具体过程在这里不予以分析,状态栏对应的类为:\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBar.java
加载这个类会首先调用它的start方法。其代码为:

 @Override
    public void start() {
        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        updateDisplaySize();

        /// M: Support Smartbook Feature.
        if (SIMHelper.isMediatekSmartBookSupport()) {
            /// M: [ALPS01097705] Query the plug-in state as soon as possible.
            mIsDisplayDevice = SIMHelper.isSmartBookPluggedIn(mContext);
            Log.v(TAG, "start, mIsDisplayDevice=" + mIsDisplayDevice);
        }

        super.start(); // calls createAndAddWindows()

        addNavigationBar(); 

        // Lastly, call to the icon policy to install/update all the icons.
        mIconPolicy = new PhoneStatusBarPolicy(mContext);

        mHeadsUpObserver.onChange(true); // set up
        if (ENABLE_HEADS_UP) {
            mContext.getContentResolver().registerContentObserver(
                    Settings.Global.getUriFor(SETTING_HEADS_UP), true,
                    mHeadsUpObserver);
        }
    }

这个方法重写了父类\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\BaseStatusBar.java的start方法和调用了一个添加NavigationBar的方法,我们这里比较关心的是父类的这个start方法,来看看他的源码:

public void start() {
        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
        mDisplay = mWindowManager.getDefaultDisplay();

        mDreamManager = IDreamManager.Stub.asInterface(
                ServiceManager.checkService(DreamService.DREAM_SERVICE));
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);

        mProvisioningObserver.onChange(false); // set up
        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
                mProvisioningObserver);

        mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

        mRecents = getComponent(RecentsComponent.class);

        mLocale = mContext.getResources().getConfiguration().locale;
        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);

        // Connect in to the status bar manager service
        StatusBarIconList iconList = new StatusBarIconList();
        ArrayList notificationKeys = new ArrayList();
        ArrayList notifications = new ArrayList();
        mCommandQueue = new CommandQueue(this, iconList);

        int[] switches = new int[7];
        ArrayList binders = new ArrayList();
        try {
            mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
                    switches, binders);
        } catch (RemoteException ex) {
            // If the system process isn't there we're doomed anyway.
        }

        createAndAddWindows();

        disable(switches[0]);
        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]);
        setHardKeyboardStatus(switches[5] != 0, switches[6] != 0);

        // Set up the initial icon state
        int N = iconList.size();
        int viewIndex = 0;
        for (int i=0; iif (icon != null) {
                addIcon(iconList.getSlot(i), i, viewIndex, icon);
                viewIndex++;
            }
        }

        // Set up the initial notification state
        N = notificationKeys.size();
        if (N == notifications.size()) {
            for (int i=0; iget(i), notifications.get(i));
            }
        } else {
            Log.wtf(TAG, "Notification list length mismatch: keys=" + N
                    + " notifications=" + notifications.size());
        }

        if (DEBUG) {
            Log.d(TAG, String.format(
                    "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
                   iconList.size(),
                   switches[0],
                   switches[1],
                   switches[2],
                   switches[3]
                   ));
        }

        mCurrentUserId = ActivityManager.getCurrentUser();

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_SWITCHED);
        mContext.registerReceiver(mBroadcastReceiver, filter);
    }

这里实例化了一些服务类和管理类,并且对通知和系统图标做了一些初始化工作,其中调用了一个createAndAddWindows方法,这个方法做了哪些工作呢?这个一个抽象方法,那应该就是在其子类实现,我们回到PhoneStatusBar类中,果然有相应的实现

@Override
    public void createAndAddWindows() {
        addStatusBarWindow();
    }

来看看addStatusBarWindow方法:

 private void addStatusBarWindow() {
        // Put up the view
        final int height = getStatusBarHeight();

        // Now that the status bar window encompasses the sliding panel and its
        // translucent backdrop, the entire thing is made TRANSLUCENT and is
        // hardware-accelerated.
        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                height,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);

        lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;

        lp.gravity = getStatusBarGravity();
        lp.setTitle("StatusBar");
        lp.packageName = mContext.getPackageName();

        makeStatusBarView();

        /// M: [SystemUI] For SystemUI AT.
        if (AutoTestHelper.isNotRunningInTest()) {
            mWindowManager.addView(mStatusBarWindow, lp);
            isStatusBarShow = true;
        }
        int state = Settings.System.getInt(mContext.getContentResolver(), Settings.System.STATUSBAR_HIDE, -1);
        if(state == 1){
            mStatusBarWindow.setVisibility(View.GONE);
            mNavigationBarView.setVisibility(View.GONE);
            isStatusBarShow = false;
        }
    }

这里主要调用了makeStatusBarView这个方法,这个方法主要是用来构建状态栏的View

protected PhoneStatusBarView makeStatusBarView() {
if (FeatureOption.MTK_GEMINI_SUPPORT) {
     mStatusBarWindow = (StatusBarWindowView)View.inflate(context, R.layout.gemini_super_status_bar, null);
} else {
     mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);
}

mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);

 // Quick Settings (where available, some restrictions apply)
        if (mHasSettingsPanel) {
            // first, figure out where quick settings should be inflated
            final View settings_stub;
            if (mHasFlipSettings) {
                // a version of quick settings that flips around behind the notifications
                settings_stub = mStatusBarWindow.findViewById(R.id.flip_settings_stub);
                if (settings_stub != null) {
                    mFlipSettingsView = ((ViewStub)settings_stub).inflate();
                    mFlipSettingsView.setVisibility(View.GONE);
                    mFlipSettingsView.setVerticalScrollBarEnabled(false);
                }
            } else {
                // full quick settings panel
                settings_stub = mStatusBarWindow.findViewById(R.id.quick_settings_stub);
                if (settings_stub != null) {
                    mSettingsPanel = (SettingsPanelView) ((ViewStub)settings_stub).inflate();
                } else {
                    mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
                }

                if (mSettingsPanel != null) {
                    if (!ActivityManager.isHighEndGfx()) {
                        mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
                                R.color.notification_panel_solid_background)));
                    }
                }
            }

            // wherever you find it, Quick Settings needs a container to survive
            mSettingsContainer = (QuickSettingsContainerView)
                    mStatusBarWindow.findViewById(R.id.quick_settings_container);
            if (mSettingsContainer != null) {
                mQS = new QuickSettings(mContext, mSettingsContainer);
                if (!mNotificationPanelIsFullScreenWidth) {
                    mSettingsContainer.setSystemUiVisibility(
                            View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
                            | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
                }
                if (mSettingsPanel != null) {
                    mSettingsPanel.setQuickSettings(mQS);
                }
                mQS.setService(this);
                mQS.setBar(mStatusBarView);
                mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
                        mLocationController, mRotationLockController);
            } else {
                mQS = null; // fly away, be free
            }
        }

这里只列出了关键代码,实例化了一个mStatusBarView 对象,然后创建快速设置的显示面板,接着创建一个快速设置的容器,并利用这个容器来创建了一个QuickSettings对象,最后把这个对象添加到显示面板mSettingsPanel中,QuickSettings路径为:\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\QuickSettings.java

接下来QuickSettings对象mQS调用了setup方法,来看看这个方法:

void setup(NetworkController networkController, BluetoothController bluetoothController,
            BatteryController batteryController, LocationController locationController,
            RotationLockController rotationLockController) {
        mBluetoothController = bluetoothController;
        mRotationLockController = rotationLockController;
        mLocationController = locationController;

        setupQuickSettings();
        updateResources();
        applyLocationEnabledStatus();

        /// M: We control BT state in QuickSettingsConnectionModel.
        ///networkController.addNetworkSignalChangedCallback(mModel);
        ///bluetoothController.addStateChangedCallback(mModel);
        batteryController.addStateChangedCallback(mModel);
        /// M: Support Laptop Battery on QS.
        batteryController.addLaptopStateChangedCallback(mModel);
        locationController.addSettingsChangedCallback(mModel);
        rotationLockController.addRotationLockControllerCallback(mModel);
    }

接着进入setupQuickSettings方法:

private void setupQuickSettings() {
        // Setup the tiles that we are going to be showing (including the temporary ones)
        LayoutInflater inflater = LayoutInflater.from(mContext);

        addUserTiles(mContainerView, inflater);
        addSystemTiles(mContainerView, inflater);
        addTemporaryTiles(mContainerView, inflater);
        IQuickSettingsPlugin quickSettingsPlugin = PluginFactory.getQuickSettingsPlugin(mContext);
        quickSettingsPlugin.customizeTileViews(mContainerView);

        queryForUserInformation();
        queryForSslCaCerts();
        mTilesSetUp = true;

        /// M: [SystemUI] Add quick settings function(airplane, data conn, bluetooth, timeout, gps, etc.) @{.
        mQuickSettingsConnectionModel.buildIconViews();
        new Handler().postDelayed(new Runnable() {
            public void run() {
                setUpdate();
                mQuickSettingsConnectionModel.setUpdates(true);
                mQuickSettingsConnectionModel.initConfigurationState();
            }
        }, 200);
        /// M: [SystemUI] Add quick settings function(airplane, data conn, bluetooth, timeout, gps, etc.) @}.
    }

addUserTiles方法是添加快速设置中的用户选项,addSystemTiles方法添加了Wifi,蓝牙转屏等选项

 private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
        /// M: MTK Quick Setting.
        addLaptopBatteryTile(parent, inflater);
        addBatteryTile(parent, inflater);
        addSettingTile(parent, inflater);

        addWifiTile(parent, inflater);
        addBluetoothTile(parent, inflater);
        addLocationTile(parent, inflater);
        addStatusBarTile(parent, inflater);

        addAirplaneTile(parent, inflater);
        addDataConnectionTile(parent, inflater);
        addDataUsageTile(parent, inflater);

        addAudioProfileTile(parent, inflater);
        addBrightnessTile(parent, inflater);
        addRotationTile(parent, inflater);

        addTimeoutTile(parent, inflater);
    }

在此,我们添加了一个addStatusBarTile方法,用于添加隐藏状态栏选项,代码为:

private void addStatusBarTile(ViewGroup parent, LayoutInflater inflater) {
        /// M: StatusBar Tile
        final QuickSettingsBasicTile statusBarTile = 
            new QuickSettingsBasicTile(mContext, null, R.layout.mtk_quick_settings_tile_basic);
        statusBarTile.setTileViewId(QuickSettingsTileViewId.ID_StatusBar);
        parent.addView(statusBarTile);

        mQuickSettingsConnectionModel.addStatusBarTile(statusBarTile);
    }

这里首先声明了一个statusBarTile的view对象,然后设置了这个statusBarTile的显示的标题,再把这个statusBarTile对象添加到parent也就是mContainerView中,最后把statusBarTile添加到mQuickSettingsConnectionModel对象中,看看它的源码:

public void addStatusBarTile(View statusBarView) {
        mStatusBarTileView = statusBarView;
        mStatusBarLayout = (FrameLayout) mStatusBarTileView.findViewById(R.id.layout);
        mStatusBarIcon = (ImageView) mStatusBarTileView.findViewById(R.id.image);
    }

这里很简单,只是获取隐藏状态栏选项的view,布局和image。

回到setupQuickSettings方法中,接着会创建一个子线程,在这个子线程中会调用mQuickSettingsConnectionModel对象的initConfigurationState方法,看看源码:

public void initConfigurationState() {
        boolean isAirlineModeOn = isAirplaneModeOn(mContext);
        if (FeatureOption.MTK_WLAN_SUPPORT) {
            if (PluginFactory.getStatusBarPlugin(mContext).supportDisableWifiAtAirplaneMode()) {
                mWifiStateTracker.setAirlineMode(isAirlineModeOn);
                mWifiTileView.setEnabled(mWifiStateTracker.isClickable());
            }
            mWifiStateTracker.setImageViewResources(mContext);
        }
        if (FeatureOption.MTK_BT_SUPPORT) {
            if (PluginFactory.getStatusBarPlugin(mContext).supportDisableBluetoothAtAirplaneMode()) {
                mBluetoothStateTracker.setAirlineMode(isAirlineModeOn);
                mBluetoothTileView.setEnabled(mBluetoothStateTracker.isClickable());
            }
            mBluetoothStateTracker.setImageViewResources(mContext);
        }
        mAirlineModeStateTracker.setImageViewResources(mContext);
        /// M: only apply if NOT wifi-only device @{
        if (!isWifiOnlyDevice()) {
        /// M: }@
            mMobileStateTracker.setAirlineMode(isAirlineModeOn);
            mMobileStateTracker.setHasSim(false);
            mMobileStateTracker.setCurrentState(mContext, StateTracker.STATE_DISABLED);
            mMobileStateTracker.setImageViewResources(mContext);

            mSimCardReady = SystemProperties.getBoolean(TelephonyProperties.PROPERTY_SIM_INFO_READY, false);
            if (mSimCardReady) {
                Xlog.d(TAG, "Oops, sim ready, maybe phone is drop down and restarted");
                List.SimInfoRecord> simInfos = SIMHelper.getSIMInfoList(mContext);
                if (simInfos == null || simInfos.size() <= 0) {
                    mMobileStateTracker.setHasSim(false);
                } else {
                    mMobileStateTracker.setHasSim(true);
                }
                mMobileTileView.setEnabled(mMobileStateTracker.isClickable());
                mMobileStateTracker.setImageViewResources(mContext);
            }
        /// M: only apply if NOT wifi-only device @{
        }
        /// M: }@
        if (ENABLE_TIMEOUT) {
            mTimeoutStateTracker.setImageViewResources(mContext);
        }
        mAutoRotationStateTracker.setImageViewResources(mContext);
        mStatusBarStateTracker.setImageViewResources(mContext);
        if (ENABLE_AUDIO_PROFILE) {
            if (mProfileManager.getActiveProfileKey() != null) {
                updateProfileView(AudioProfileManager.getScenario(mProfileManager.getActiveProfileKey()));
            }
        }
    }

这个方法主要对快速设置栏中初始化的操作,我们在其中添加了mStatusBarStateTracker.setImageViewResources(mContext);
那么这个mStatusBarStateTracker是个什么呢?
它是QuickSettingsConnectionModel中的一个内部类的对象,

 private final class StatusBarStateTracker extends StateTracker {
        @Override
        public int getActualState(Context context) {
            int state = Settings.System.getInt(context.getContentResolver(), Settings.System.STATUSBAR_HIDE, -1);
            if(state == -1){
                state = 0;
            }
            if (state == 1) {
                return STATE_ENABLED;
            } else if (state == 0) {
                return STATE_DISABLED;
            } else {
                return STATE_UNKNOWN;
            }
        }

        @Override
        public void onActualStateChange(Context context, Intent unused) {
            /// M: Note: the broadcast location providers changed intent
            /// doesn't include an extras bundles saying what the new value is.
            setCurrentState(context, getActualState(context));
        }

        @Override
        public void requestStateChange(final Context context, final boolean desiredState) {
            final ContentResolver resolver = context.getContentResolver();
            new AsyncTask() {
                @Override
                protected Boolean doInBackground(Void... args) {
                    Settings.System.putInt(context.getContentResolver(),
                            Settings.System.STATUSBAR_HIDE, desiredState ? 1 : 0);
                    return desiredState;
                }

                @Override
                protected void onPostExecute(Boolean result) {
                    setCurrentState(context, result ? STATE_ENABLED : STATE_DISABLED);
                    sendHideStatusBarBroadcast(result);
                }
            }.execute();
        }

        public int getDisabledResource() {
            return R.drawable.ic_qs_mobile_off;
        }

        public int getEnabledResource() {
            return R.drawable.ic_qs_mobile_enable;
        }

        public ImageView getImageButtonView() {
            return mStatusBarIcon;
        }

        @Override
        public ImageView getIndicatorView() {
            return null;
        }

        public View getTileView() {
            return mStatusBarTileView;
        }

    }

这个内部类的作用主要就是获取并修改当前状态栏的状态(是否隐藏),具体的我们后面再分析。
在子线程中,其实还有setupQuickSettings方法的子线程中,还有一个方法我们没讲,mQuickSettingsConnectionModel.setUpdates(true);
来看看这个setUpdate方法:

public void setUpdates(boolean update) {
        if (update != mUpdating) {
            if (ENABLE_AUDIO_PROFILE) {
                mProfileKeys = new ArrayList();
                mProfileKeys = mProfileManager.getPredefinedProfileKeys();
            }
            mUpdating = update;
            if (update) {
                IntentFilter filter = new IntentFilter();
                if (FeatureOption.MTK_WLAN_SUPPORT) {
                    filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
                }
                if (FeatureOption.MTK_BT_SUPPORT) {
                    filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
                }
                /// M: for mobile config
                filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
                filter.addAction(TelephonyIntents.ACTION_SIM_INDICATOR_STATE_CHANGED);
                filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
                filter.addAction(TRANSACTION_START);
                filter.addAction(TRANSACTION_STOP);
                filter.addAction(IPO_BOOT);
                filter.addAction(Intent.ACTION_BOOT_COMPLETED);
                refreshDataUsageTile();
                mContext.registerReceiver(mIntentReceiver, filter);
                if (FeatureOption.MTK_GEMINI_SUPPORT) {
                    mContext.getContentResolver().registerContentObserver(
                            Settings.System.getUriFor(Settings.System.GPRS_CONNECTION_SIM_SETTING)
                            , true, mMobileStateChangeObserver);
                } else {
                    mContext.getContentResolver().registerContentObserver(
                            Settings.Secure.getUriFor(Settings.Global.MOBILE_DATA)
                            , true, mMobileStateForSingleCardChangeObserver);
                }
                /// M: get notified of phone state changes
                TelephonyManager telephonyManager = (TelephonyManager) mContext
                        .getSystemService(Context.TELEPHONY_SERVICE);
                if (FeatureOption.MTK_GEMINI_SUPPORT) {
                    /// M: Support GeminiPlus
                    for (int i = PhoneConstants.GEMINI_SIM_1; i < PhoneConstants.GEMINI_SIM_1 + PhoneConstants.GEMINI_SIM_NUM; i++) {
                        SIMHelper.listen(mPhoneStateListenerGemini, PhoneStateListener.LISTEN_SERVICE_STATE, i);
                    }
                } else {
                    telephonyManager.listen(mPhoneStateListener1,
                            PhoneStateListener.LISTEN_SERVICE_STATE);
                }
                mContext.getContentResolver().registerContentObserver(
                        Settings.System.getUriFor(Settings.System.SCREEN_OFF_TIMEOUT),
                        true, mTimeoutChangeObserver, mUserTracker.getCurrentUserId());
                mContext.getContentResolver().registerContentObserver(
                        Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
                        true, mAutoRotationChangeObserver);
                mContext.getContentResolver().registerContentObserver(
                        Settings.System.getUriFor(Settings.System.STATUSBAR_HIDE),
                        true, mStatusBarChangeObserver);

                /// M: Register for Intent broadcasts for the clock and battery
                Xlog.d(TAG, "setUpdates: listenAudioProfie with mAudioProfileListenr = " + mAudioProfileListenr);
                if (ENABLE_AUDIO_PROFILE) {
                    mProfileManager.listenAudioProfie(mAudioProfileListenr, AudioProfileListener.LISTEN_AUDIOPROFILE_CHANGEG);
                }
            } else {
                mContext.unregisterReceiver(mIntentReceiver);
                if (FeatureOption.MTK_GEMINI_SUPPORT) {
                    mContext.getContentResolver().unregisterContentObserver(
                            mMobileStateChangeObserver);
                } else {
                    mContext.getContentResolver().unregisterContentObserver(
                            mMobileStateForSingleCardChangeObserver);
                }
                TelephonyManager telephonyManager = (TelephonyManager) mContext
                        .getSystemService(Context.TELEPHONY_SERVICE);
                if (FeatureOption.MTK_GEMINI_SUPPORT) {
                    /// M: Support GeminiPlus
                    for (int i = PhoneConstants.GEMINI_SIM_1; i < PhoneConstants.GEMINI_SIM_1 + PhoneConstants.GEMINI_SIM_NUM; i++) {
                        SIMHelper.listen(mPhoneStateListenerGemini, 0, i);
                    }
                } else {
                    telephonyManager.listen(mPhoneStateListener1, 0);
                }
                mContext.getContentResolver().unregisterContentObserver(mTimeoutChangeObserver);
                mContext.getContentResolver().unregisterContentObserver(mAutoRotationChangeObserver);
                mContext.getContentResolver().unregisterContentObserver(mStatusBarChangeObserver);
                if (ENABLE_AUDIO_PROFILE) {
                    mProfileManager.listenAudioProfie(mAudioProfileListenr, AudioProfileListener.LISTEN_NONE);
                }
            }
        }
    }

这里用到了ContentObserver内容观察者,用于监视快速设置中选项的变化,我们添加了如下代码:mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.STATUSBAR_HIDE),
true, mStatusBarChangeObserver);

来看看mStatusBarChangeObserver的实现:

private ContentObserver mStatusBarChangeObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
            mStatusBarStateTracker.onActualStateChange(mContext, null);
            mStatusBarStateTracker.setImageViewResources(mContext);
        }
    };

当选项状态发生改变时,mStatusBarStateTracker对象就会获取当前的 状态,并对新的状态进行设置。我们接下来分析StatusBarStateTracker:

private final class StatusBarStateTracker extends StateTracker {
        @Override
        public int getActualState(Context context) {
            int state = Settings.System.getInt(context.getContentResolver(), Settings.System.STATUSBAR_HIDE, -1);
            if(state == -1){
                state = 0;
            }
            if (state == 1) {
                return STATE_ENABLED;
            } else if (state == 0) {
                return STATE_DISABLED;
            } else {
                return STATE_UNKNOWN;
            }
        }

        @Override
        public void onActualStateChange(Context context, Intent unused) {
            /// M: Note: the broadcast location providers changed intent
            /// doesn't include an extras bundles saying what the new value is.
            setCurrentState(context, getActualState(context));
        }

        @Override
        public void requestStateChange(final Context context, final boolean desiredState) {
            final ContentResolver resolver = context.getContentResolver();
            new AsyncTask() {
                @Override
                protected Boolean doInBackground(Void... args) {
                    Settings.System.putInt(context.getContentResolver(),
                            Settings.System.STATUSBAR_HIDE, desiredState ? 1 : 0);
                    return desiredState;
                }

                @Override
                protected void onPostExecute(Boolean result) {
                    setCurrentState(context, result ? STATE_ENABLED : STATE_DISABLED);
                    sendHideStatusBarBroadcast(result);
                }
            }.execute();
        }

        public int getDisabledResource() {
            return R.drawable.ic_qs_mobile_off;
        }

        public int getEnabledResource() {
            return R.drawable.ic_qs_mobile_enable;
        }

        public ImageView getImageButtonView() {
            return mStatusBarIcon;
        }

        @Override
        public ImageView getIndicatorView() {
            return null;
        }

        public View getTileView() {
            return mStatusBarTileView;
        }

    }

当执行onActualStateChange方法时会执行setCurrentState方法,而执行setCurrentState又会调用requestStateChange方法,

public final void setCurrentState(Context context, int newState) {
        final boolean wasInTransition = mInTransition;
        switch (newState) {
        case STATE_DISABLED:
            mInTransition = false;
            mActualState = false;
            break;
        case STATE_ENABLED:
            mInTransition = false;
            mActualState = true;
            break;
        case STATE_TURNING_ON:
            mInTransition = true;
            mActualState = false;
            break;
        case STATE_TURNING_OFF:
            mInTransition = true;
            mActualState = true;
            break;
        default:
            break;
        }

        if (wasInTransition && !mInTransition) {
            if (mDeferredStateChangeRequestNeeded) {
                Xlog.v(TAG, "processing deferred state change");
                if (mActualState != null && mIntendedState != null
                        && mIntendedState.equals(mActualState)) {
                    Xlog.v(TAG, "... but intended state matches, so no changes.");
                } else if (mIntendedState != null) {
                    mInTransition = true;
                    requestStateChange(context, mIntendedState);
                }
                mDeferredStateChangeRequestNeeded = false;
            }
        }
    }

在requestStateChange有个异步任务用于设置新的选项值,并发送一个广播,这个广播的作用是通知PhoneStatusBar可以隐藏或显示状态栏和导航栏了,

private void sendHideStatusBarBroadcast(boolean isStatusBarHide){
        Intent intent = new Intent();
        intent.putExtra("isStatusBarHide", isStatusBarHide);  
        intent.setAction("com.android.hide_status_bar");  
        mContext.sendBroadcast(intent); 
    }

接下来我们看看这个广播被接收后做了哪些处理。

private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
        else if (STATUS_BAR_HIDE_ACTION.equals(action)) {
                boolean isStatusBarHide = intent.getExtras().getBoolean("isStatusBarHide");
                //Log.e("dy","isStatusBarHide == "+String.valueOf(isStatusBarHide));
                //Log.e("dy","isStatusBarShow == "+String.valueOf(isStatusBarShow));
                if(!isStatusBarHide){
                    mStatusBarWindow.setVisibility(View.VISIBLE);
                    mNavigationBarView.setVisibility(View.VISIBLE);
                    isStatusBarShow = true;
                    Log.e("dy","show");
                }
                if(isStatusBarHide){
                    mStatusBarWindow.setVisibility(View.GONE);
                    mNavigationBarView.setVisibility(View.GONE);
                    isStatusBarShow = false;
                    Log.e("dy","hide");
                }
            }
            else if (!isExpandedInvisible&&STATUS_BAR_HIDING_ACTION.equals(action)) {
                boolean isStatusBarHiding = intent.getExtras().getBoolean("isStatusBarHiding");
                if(!isStatusBarHiding&&!isStatusBarShow){
                    mStatusBarWindow.setVisibility(View.VISIBLE);
                }
                if(isStatusBarHiding&&!isStatusBarShow){
                    mStatusBarWindow.setVisibility(View.GONE);
                }
            }
}

这里其实挺简单,就是根据广播传过来的 属性 值,对状态栏和导航栏进行显示和隐藏。

Android快速设置中添加隐藏状态栏和导航栏选项的分析到此结束!

你可能感兴趣的:(Android,NavigationBar,SystemUI,StatusBar)