Android immersive status bar - font color and background color modification implementation and compatibility

Keywords: Flyme Android MIUI Mobile

Immersive status bar research is to extend the layout content to the status bar, so that the status bar can be covered or hidden on the layout.

Realization

First of all, to modify the android version of the status bar at least above 4.4, and in 4.4, it is not allowed to make the status bar transparent, only to achieve a translucent shadow background, while in 5.x version, it is possible to modify the background color but not the font color, only in 6.0 and above can be modified at will. But in Meizu and Xiaomi's third-party ROM s above version 4.4, mobile phones provide modified interfaces. So the specific modification code is as follows:

/**
     * Modify the status bar to be fully transparent and non occupied
     */
@TargetApi(19)
public static void transparencyBar(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

This method satisfies the situation that some pictures are immersed in the status bar at the top.
However, in some cases, we don't put pictures on the top. In order not to make the fonts of the text and the status bar interlace, we need a space occupying background of the status bar:

  /**
     * Add status bar placeholder view
     * After removing the status bar, the content will overlap the status bar and this will occupy the space
     */
    public static void addStatusView(Activity activity, ViewGroup contentView) {
        View statusBarView = new View(activity);
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                getStatusBarHeight(activity));
        statusBarView.setBackgroundColor(ContextCompat.getColor(activity, R.color.status));
        statusBarView.setLayoutParams(lp);
        contentView.addView(statusBarView, 0);
    }

    /**
     * Using reflection to get the height of status bar
     */
    private static int getStatusBarHeight(Activity activity) {
        int result = 0;
        //Get the resource id of the status bar height
        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = activity.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

The defect of this method is that the root layout of the layout file needs to be a LinearLayout, which has limitations. Of course, it's also Vertical.

Finally, paste the code of the whole tool class:

It includes compatible methods for modifying fonts and background colors.

public class StatusBarUtil {
    private static final int MIUI = 1;
    private static final int FLYME = 2;
    private static final int ANDROID_M = 3;

    /**
     * Modify the status bar to be fully transparent and non occupied
     */
    @TargetApi(19)
    public static void transparencyBar(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    /**
     * Add status bar placeholder view
     * After removing the status bar, the content will overlap the status bar and this will occupy the space
     */
    public static void addStatusView(Activity activity, ViewGroup contentView) {
        View statusBarView = new View(activity);
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                getStatusBarHeight(activity));
        statusBarView.setBackgroundColor(ContextCompat.getColor(activity, R.color.status));
        statusBarView.setLayoutParams(lp);
        contentView.addView(statusBarView, 0);
    }

    /**
     * Using reflection to get the height of status bar
     */
    private static int getStatusBarHeight(Activity activity) {
        int result = 0;
        //Get the resource id of the status bar height
        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = activity.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    /**
     * Status bar light color mode, setting status bar black text, icon,
     * Adapts to MIUIV, Flyme and other Android versions above 4.4 and 6.0
     *
     * @return 1:MIUUI 2:Flyme 3:android6.0
     */
    public static int setStatusBarLightMode(Activity activity) {
        int result = 0;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (MIUISetStatusBarLightMode(activity, true)) {
                result = MIUI;
            } else if (FLYMESetStatusBarLightMode(activity.getWindow(), true)) {
                result = FLYME;
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                result = ANDROID_M;
            }
        }
        return result;
    }

    /**
     * When the system type is known, set the black text and icon in the status bar.
     * Adapts to MIUIV, Flyme and other Android versions above 4.4 and 6.0
     *
     * @param type 1:MIUUI 2:Flyme 3:android6.0
     */
    public static void setStatusBarLightMode(Activity activity, int type) {
        if (type == MIUI) {
            MIUISetStatusBarLightMode(activity, true);
        } else if (type == FLYME) {
            FLYMESetStatusBarLightMode(activity.getWindow(), true);
        } else if (type == ANDROID_M) {
            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
    }

    /**
     * Status bar dark mode, clear the status bar black text and icon of MIUI, flyme or above version 6.0
     */
    public static void setStatusBarDarkMode(Activity activity, int type) {
        if (type == MIUI) {
            MIUISetStatusBarLightMode(activity, false);
        } else if (type == FLYME) {
            FLYMESetStatusBarLightMode(activity.getWindow(), false);
        } else if (type == ANDROID_M) {
            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
        }
    }

    /**
     * Set status bar icons to dark and Meizu specific text styles
     * It can be used to determine whether it is a Flyme user
     *
     * @param window Windows to set
     * @param dark   Set the status bar text and icon color to dark
     * @return boolean Successful execution returns true
     */
    private static boolean FLYMESetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class
                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class
                        .getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {

            }
        }
        return result;
    }

    /**
     * Need MIUIV6 or above
     *
     * @param dark Set the status bar text and icon color to dark
     * @return boolean Successful execution returns true
     */
    private static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
        boolean result = false;
        Window window = activity.getWindow();
        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if (dark) {
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//Status bar transparent and black font
                } else {
                    extraFlagField.invoke(window, 0, darkModeFlag);//Clear black font
                }
                result = true;

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    //Development version 7.7.13 and later uses system API, the old method is invalid but will not report errors, so both methods should be added
                    if (dark) {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                    } else {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}

Posted by ruddyu78 on Sat, 02 May 2020 20:52:59 -0700