Recently, I met a personalized requirement in the development, which is similar to the realization of the gradual status bar on the top of QQ, as shown in the following figure

On Android5.0, the system API allows you to directly set the StatusBar to change the color of the StatusBar. On android 4.4, however, the basic principle for changing the color of the StatusBar is to make the StatusBar itself transparent. Then add a View of the same size in the StatusBar position and color it. We have to make a gradient color status bar that is compatible with the differences between the upper and lower versions

For more information about the immersive status bar, see Hongyang Dashen’s article

Let your status bar change color

Solid color compatible status bar

/** * set the status bar color ** @param activity Specifies the activity * @param color status bar color * @param statusBarAlpha status bar transparency */ public static voidsetColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {
        if(build.version.sdk_int >= build.version_codes.lollipop) {// Higher than 5.0 // Can be called only by setting flag_drawS_system_bar_BACKGROUNDsetStatusBarColor methods to set the status bar color activity. GetWindow () addFlags (WindowManager. LayoutParams. FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); / / set FLAG_TRANSLUCENT_STATUS transparent status bar activity. GetWindow (). ClearFlags (WindowManager. LayoutParams. FLAG_TRANSLUCENT_STATUS); // Display activity.getwindow ().setStatusBarColor(calculateStatusColor(color, statusBarAlpha)) based on the entered color and transparency; }else if(build.version.sdk_int >= build.version_codes.kitkat) {// Lower VERSION // Add transparent status bar activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); ViewGroup decorView = (ViewGroup) activity.getwindow ().getDecorView(); // Get the top StatusBarView, customize the Id of the StatusBarView (create Id in resources) View fakeStatusBarView = decorView.findViewById(R.id.statusbarutil_fake_status_bar_view);if(fakeStatusBarView ! = null) {if(fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } / / set the top color fakeStatusBarView. SetBackgroundColor (calculateStatusColor (color, statusBarAlpha)); }elseDecorviet. addView(createStatusBarView(Activity, color, statusBarAlpha)); }setRootView(activity); }}Copy the code

CalculateStatusColor (Calculate status bar color)

/** * Calculate the status bar color ** @param color color value * @param alpha alpha value * @return*/ private static int calculateStatusColor(@colorint int color, int alpha) {if (alpha == 0) {
            return color;
        }
        float a = 1 - alpha / 255f;
        int red = color >> 16 & 0xff;
        int green = color >> 8 & 0xff;
        int blue = color & 0xff;
        red = (int) (red * a + 0.5);
        green = (int) (green * a + 0.5);
        blue = (int) (blue * a + 0.5);
        return 0xff << 24 | red << 16 | green << 8 | blue;
    }
Copy the code

Custom View status bar

/** * custom View status bar ** @param activity Required to set the activity * @param color status bar color * @param alpha transparent value * @return*/ private static View createStatusBarView(Activity Activity, @colorInt int color, View statusBarView = new View(Activity); // Draw a rectangle with the same height as the status bar. LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setLayoutParams(params); statusBarView.setBackgroundColor(calculateStatusColor(color, alpha)); SetId (FAKE_STATUS_BAR_VIEW_ID); // The default StatusBarView Id is statusbarview. setId(FAKE_STATUS_BAR_VIEW_ID);return statusBarView;
    }
Copy the code

Finally, redesign the layout

setRootView

/** * Sets the root layout parameter */ private static voidsetRootView(Activity Activity) {//ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);for (int i = 0, count = parent.getChildCount(); i < count; i++) {
            View childView = parent.getChildAt(i);
            if (childView instanceof ViewGroup) {
                childView.setFitsSystemWindows(true);
                ((ViewGroup) childView).setClipToPadding(true); }}}Copy the code

The basic configuration of the solid color status bar is ok. Just create the Utils utility class to call in the Activity.

// Set the solid-color status bar statusBarutil.setcolor (this, apputils.getColor (r.color.colorPrimary));Copy the code

Gradient compatible status bar

The following code

/** * @param Activity Specifies the activity to be set. * @param statusBarAlpha specifies the status bar transparency. * @param needOffsetView specifies the downward offset View public static voidsetTranslucentForWindow(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,
                                                  View needOffsetView) {
        if(build.version.sdk_int > build.version_codes.kitkat) {// VERSION 5.0 or latersetTransparentForWindow(activity);
            addTranslucentView(activity, statusBarAlpha);
            if(needOffsetView ! = null) { Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET);if(haveSetOffset ! = null && (Boolean) haveSetOffset) {return;
                }
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();
                layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity),
                        layoutParams.rightMargin, layoutParams.bottomMargin);
                needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true); }}else{/ / / / low version status bar activity. The transparent getWindow () addFlags (WindowManager. LayoutParams. FLAG_TRANSLUCENT_STATUS); ViewGroup decorView = (ViewGroup) activity.getwindow ().getDecorView(); FakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);if(fakeStatusBarView ! = null) {if(fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } / / set the top color fakeStatusBarView. SetBackgroundResource (R.d rawable. Shape_gradient); }elseView statusBarView = new View(activity); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setLayoutParams(params); fakeStatusBarView.setBackgroundResource(R.drawable.shape_gradient); statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID); decorView.addView(statusBarView); }setRootView(activity); }}Copy the code

getStatusBarHeight

/** * get the status bar height ** @param context context * @returnStatus bar height */ public static int getStatusBarHeight(Context Context) {// getStatusBarHeight int resourceId = context.getResources().getIdentifier("status_bar_height"."dimen"."android");
        return context.getResources().getDimensionPixelSize(resourceId);
    }
Copy the code

setTransparentForWindow

/** * transparent */ public static voidsetTransparentForWindow(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
            activity.getWindow()
                    .getDecorView()
                    .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow()
                    .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
Copy the code

addTranslucentView

/** * add a translucent rectangle ** @param Activity To set the activity * @param statusBarAlpha transparent value */ private static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); FakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);if(fakeTranslucentView ! = null) {if (fakeTranslucentView.getVisibility() == View.GONE) {
                fakeTranslucentView.setVisibility(View.VISIBLE);
            }
            fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));
        } else{ contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha)); }}Copy the code

To set the status bar for this gradient color, simply pass in the Toolbar as a View, called as follows

/ / set the gradient color status bar StatusBarUtil. SetTransparentForWindow (this, mToolbar); // The layout is like <? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
 
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/shape_gradient"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:elevation="@dimen/dp0">
 
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="? attr/actionBarSize"
            app:popupTheme="@style/ToolbarPopupTheme"
            app:title="@string/main_toolbar_title_top"
            app:titleTextColor="@color/colorPrimary">
 
 
        </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>
</LinearLayout>
Copy the code

Demo Link

At this point, the configuration of the gradient status bar is completely covered