One, foreword

I’m not actually going to write this article. Why? Because there are so many articles about the immersive status bar, just Google it and you can find dozens or hundreds of articles, some of which are good and some of which are just there. When we launched a series of Material Design articles on our official account, some readers left comments, hoping to write an article about immersion. Therefore, this article will summarize the implementation principle of each version, and recommend a library that I think is very convenient for you.

Second, immersive general routines

Before introducing this handy wheel, let’s review the general approach to implementing an immersive status bar. On Android, the StatusBar (StatusBar) is getting better and better all the time. Below Android4.4, you can show and hide the StatusBar and NavigationBar. But it wasn’t until Android4.4 that we actually implemented an immersive status bar. From Android4.4 to now (Android 7.1), immersion can be roughly divided into three stages:

  • Android4.4 (API 19) – Android 5.0 (API 21) : This stage can achieve immersion, but not very well. FLAG_TRANSLUCENT_STATUS makes the StatusBar transparent and full-screen, and then immersive by adding a View of the same size as the StatusBar and setting its background to the color we want.

  • Android 5.0 (API 21) and later: In Android 5.0, we added an important property and method Android :statusBarColor (the corresponding method is setStatusBarColor), which makes it easy to implement immersion. That said, starting with Android5.0, the system really supports immersion.

  • Android6.0 (API 23) and above: Android6.0 and above is implemented in the same way as Android 5.0 +, so why classify it as a single important phase? Since Android 6.0 (API 23), we can change the drawing mode of the status bar to display white or light black content and ICONS (except for Meizu mobile phones, Meizu has made source code changes, which can be implemented below 6.0).

It’s basically the three phases, so let’s look at how these three phases are implemented.

2.1 Android4.4 (API 19) – Android 5.0 (API 21) implemented in an immersive way

Why is Android 4.4 so immersive? There is an important new attribute in Android 4.4: FLAG_TRANSLUCENT_STATUS

 /**
         * Window flag: request a translucent status bar with minimal system-provided
         * background protection.
         *
         * <p>This flag can be controlled in your theme through the
         * {@link android.R.attr#windowTranslucentStatus} attribute; this attribute
         * is automatically set for you in the standard translucent decor themes
         * such as
         * {@link android.R.style#Theme_Holo_NoActionBar_TranslucentDecor},
         * {@link android.R.style#Theme_Holo_Light_NoActionBar_TranslucentDecor},
         * {@link android.R.style#Theme_DeviceDefault_NoActionBar_TranslucentDecor}, and
         * {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_TranslucentDecor}.</p>
         *
         * <p>When this flag is enabled for a window, it automatically sets
         * the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
         * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.</p>
         */
        public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;Copy the code

Explanation: Make the status bar transparent and turn it into full screen mode. As the above explanation makes clear, when the window property is valid, The system UI visibility flags SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN are automatically set.

There are two ways to implement this property:

This can be set in code as follows:

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);Copy the code

You can also set the windowTranslucentStatus property in the theme as follows:

android:windowTranslucentStatusCopy the code

The effect is as follows:

As you can see from the image above, the immersive effect is there, but there is a problem. Our title bar and StatusBar overlap, which is equivalent to moving the StatusBar height up the layout.

To return the title bar to its original position, we add a View at the top of the title bar that is the same size as StatusBar. The BackgroundColor of the View is the same color as the title bar. This View is used as a placeholder. At this point, the title bar will be moved down the StatusBar and back to its normal position.

Add the following code:

       // Get the Windows Phone decorView
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        int       count     = decorView.getChildCount();
        // Check whether statusBarView has been added
        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
            decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
        } else {
            // Create a view that is as high and wide as the status bar
            StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
            decorView.addView(statusView);
        }
        ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
        // RootView does not leave space for the status bar
        ViewCompat.setFitsSystemWindows(rootView,true);
        rootView.setClipToPadding(true);Copy the code

The code to create a View of the same size as the Status bar is as follows:

 private static StatusBarView createStatusBarView(Activity activity, int color, int alpha) {
        // Draw a rectangle the same height as the status bar
        StatusBarView statusBarView = new StatusBarView(activity);
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
        return statusBarView;
    }Copy the code

StatusBarView is a normal View.

After adding the above code, it looks like this:

This is how you can implement the immersive status bar on Android 4.4.

Alternatively, if an image extends to the status bar, set FLAG_TRANSLUCENT_STATUS to FLAG_TRANSLUCENT_STATUS as follows:

Summary: the way to implement an immersive status bar on Android4.4 is to add the FLAG_TRANSLUCENT_STATUS Flag for your window, and then add a View station the same size as the status bar so that the title bar doesn’t overlap with the status bar. To extend an image to the status bar, set FLAG_TRANSLUCENT_STATUS.

As mentioned earlier, immersion doesn’t work very well between Android4.4 and Android5.0. As you can see from the images posted above, there is a gradient at the top of the status bar that shows a black shadow (as does the bottom navigation bar), which has been fixed in Android5.0.

2.2 Android 5.0 (API 21) above the way to achieve immersion

Android 5.0 is a milestone release. Since Android 5.0, Google has introduced a new Material Design specification, and native controls can achieve some cool UI effects. Starting with this release, Google has added an important method called setStatusBarColor (the corresponding property: Android :statusBarColor), which makes it easy to implement an immersive status bar. The method is as follows:

 /**
     * Sets the color of the status bar to {@code color}.
     *
     * For this to take effect,
     * the window must be drawing the system bar backgrounds with
     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and
     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS} must not be set.
     *
     * If {@code color} is not opaque, consider setting
     * {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
     * {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
     * <p>
     * The transitionName for the view background will be "android:status:background".
     * </p>
     */
    public abstract void setStatusBarColor(@ColorInt int color);Copy the code

Note the comments for this method. For this method to work, it must be used with a Flag, Mandatory BACKGROUND Settings for FLAG_drawS_SYSTEM_BAR_BACKGROUND

Flag_draws_system_bar_wallpapers:

As you can see, this flag was also added in Android 5.0. What does it do?

Explanation: We set the background of the Window to flag_drawS_system_bar_WALLPAPERS. Then fill the corresponding area with the colors of getStatusBarColor() and getNavigationBarColor(). This is how the immersive navigation bar is implemented on Android 5.0 and beyond.

Implement the following code for immersion:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// Clear FLAG_TRANSLUCENT_STATUS flag
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().setStatusBarColor(getResources().getColor(android.R.color.holo_red_light));Copy the code

The effect is as follows:

You can also add the following Theme to the values-v21 folder:

<style name="MDTheme" parent="Theme.Design.Light.NoActionBar"> <item name="android:windowTranslucentStatus">false</item>  <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@android:color/holo_red_light</item> </style>Copy the code

The effect is the same as the one added in the code above, so I won’t post the effect here.

The image extends to the status bar

To extend images to the status bar on Android 5.0, simply set windowTranslucentStatus and set statusBarColor to transparent:

<style name="ImageTranslucentTheme" parent="Theme.AppCompat.DayNight.NoActionBar"> <item name="android:windowTranslucentNavigation">true</item> <item name="android:windowTranslucentStatus">true</item> <! - set the statusBarColor to transparent - > < item name = "android: statusBarColor" > @ android: color/transparent < / item > < / style >Copy the code

The effect is as follows:

The code is compatible with Android5.0 or above by judging the version number:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            int count = decorView.getChildCount();
            if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
                decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
            } else {
                StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
                decorView.addView(statusView);
            }

            ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
            rootView.setFitsSystemWindows(true);
            rootView.setClipToPadding(true);
            setRootView(activity);
}Copy the code

2.3 Android 6.0 + to achieve the status bar word color and icon light black

One problem with immersion is that the Android status bar has a white color for words and ICONS. When my theme color or image color is close to white or light, I can’t see the content in the status bar. This was fixed in Android 6.0. Android 6.0 added a new property SYSTEM_UI_FLAG_LIGHT_STATUS_BAR

The Flag added to the setSystemUiVisibility(int) method requests that the Status bar draw mode, which is compatible with the status bar on a bright background. FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDSflag takes effect only when FLAG_TRANSLUCENT_STATUSflag is cleared.

Add the following code:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}Copy the code

The effect is as follows:

In addition to adding attributes in code, you can also use attributes directly in topics:

<style name="MDTheme" parent="Theme.Design.Light.NoActionBar"> <item name="android:windowTranslucentStatus">false</item>  <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@android:color/holo_red_light</item> <! - the Android 6.0 above the status bar color words and ICONS for shallow black - > < item name = "Android: windowLightStatusBar" > true < / item > < / style >Copy the code

Note: The theme should be placed in the values-v23 folder:

Three, the wheel StatusBarUtil

Through the above introduction, in fact, each version of the implementation of immersion methods and principles are finished. But maybe when you really go practice immersion status bar, you will feel a hindrance, therefore, I recommend to you a wheel StatusBarUtil, Github:github.com/laobie/Stat… .

Why is this library recommended? Because the library has only one class, StatusBarUtil, it’s easy to use, just like a utility class. There are many static methods encapsulated inside, just use them directly. It’s also easy to add your own. Here are some of the scenarios used:

It needs to be called after setContentView() :

setContentView(R.layout.main_activity); . StatusBarUtil.setColor(MainActivity.this, mColor);Copy the code
  • 1. Set the status bar color
StatusBarUtil.setColor(Activity activity, int color)Copy the code

  • 2. Make the status bar translucent
StatusBarUtil.setTranslucent(Activity activity, int statusBarAlpha)Copy the code

  • 3. Make the status bar fully transparent
StatusBarUtil.setTransparent(Activity activity)Copy the code

  • 4. Set the color of the status bar for the interface that contains DrawerLayout (translucent and transparent can also be set)
StatusBarUtil.setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int color)Copy the code

  • 5. Make the status bar transparent for the interface that uses ImageView as the Header (the common scenario is the Header part of the detail page)
StatusBarUtil.setTranslucentForImageView(Activity activity, int statusBarAlpha, View needOffsetView)Copy the code

  • 6. Use in fragments
status_uti

Four, the last

The above is a summary of the status bar of immersion, hoping to help students who have not yet used immersion. If you’ve already used the immersive status bar, take a look to get a better idea of how each version works. Finally, a good library, or more specifically, a good utility class, is recommended. If you have any questions, please let us know.

More Android dry goods articles, pay attention to the public number [Android technology grocery store]