android狀態欄背景色和圖標顏色更改總結

通過若干種方法來實現狀態欄背景和圖標變色

注意事項:api 23才支持狀態欄圖標變色,所以圖標變色會在編譯api>=23中實現
一 Android 4.4 之前狀態欄默認黑色,不能改變
二 Android 4.4 可以設置狀態欄是否透明
三 Android 5.0+ 可以主動設置狀態欄背景

1 直接代碼改變狀態欄顏色和圖標顏色
對於api在23以上的手機一行代碼可以解決 StatusBarUtils.setStatusBar(getResources().getColor(R.color.text_white),MainActivity.this);

2 使用android:fitsSystemWindows
查看6.2
3 使用paddingtop
在api>=19情況下,設置狀態欄透明,然後在根佈局中設置paddingtop=25dp,可以讓狀態欄背景色和標題欄顏色一致。用android:fitsSystemWindows效果一樣,這種方式使用起來
需要在每個根佈局中使用,用起來麻煩。不推薦使用。

4 整理小米和魅族手機狀態欄兼容方案

/**
 *狀態欄亮色模式,設置狀態欄黑色文字、圖標,
 * 適配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
 * @param activity
 * @return 1:MIUUI 2:Flyme 3:android6.0
 */
public static int StatusBarLightMode(Activity activity){
    int result=0;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        if(MIUISetStatusBarLightMode(activity, true)){
            result=1;
        }else if(FlymeSetStatusBarLightMode(activity.getWindow(), true)){
            result=2;
        }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=3;
        }
    }
    return result;
}

/**
 * 已知系統類型時,設置狀態欄黑色文字、圖標。
 * 適配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
 * @param activity
 * @param type 1:MIUUI 2:Flyme 3:android6.0
 */
public static void StatusBarLightMode(Activity activity,int type){
    if(type==1){
       MIUISetStatusBarLightMode(activity, true);
    }else if(type==2){
        FlymeSetStatusBarLightMode(activity.getWindow(), true);
    }else if(type==3){
        activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }

}

/**
 * 狀態欄暗色模式,清除MIUI、flyme或6.0以上版本狀態欄黑色文字、圖標
 */
public static void StatusBarDarkMode(Activity activity,int type){
    if(type==1){
        MIUISetStatusBarLightMode(activity, false);
    }else if(type==2){
        FlymeSetStatusBarLightMode(activity.getWindow(), false);
    }else if(type==3){
        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
    }

}


/**
 * 設置狀態欄圖標爲深色和魅族特定的文字風格
 * 可以用來判斷是否爲Flyme用戶
 * @param window 需要設置的窗口
 * @param dark 是否把狀態欄文字及圖標顏色設置爲深色
 * @return  boolean 成功執行返回true
 *
 */
public 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;
}

 /**
 * 需要MIUIV6以上
 * @param activity
 * @param dark 是否把狀態欄文字及圖標顏色設置爲深色
 * @return  boolean 成功執行返回true
 *
 */
public 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);//狀態欄透明且黑色字體
            }else{
                extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字體
            }
            result=true;

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                //開發版 7.7.13 及以後版本採用了系統API,舊方法無效但不會報錯,所以兩個方式都要加上
                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){

        }
    }
    return result;
}

5 對於api大於等於21小於23情況分析

僅僅只需要在color文件夾中改變 colorPrimaryDark的顏色(或者參照1中的方案,也可以實現效果),但圖標字體顏色無法改變
Yes it’s possible to change it to gray (no custom colors) but this only works from API 23 and above you only need to add this in your values-v23/styles.xml
true

6 對於api大於等於19小於21情況分析
注意事項:
6.1 主題是Fullscreen,狀態欄會不發生變化,因爲Fullscreen屬性會默認狀態欄不可見

<style name="AppTheme" parent="android:Theme.Light.NoTitleBar">
<!--<style name="AppTheme" parent="android:Theme.DeviceDefault.Light.DarkActionBar">-->

6.2 如果主題中使用了標題欄 actionbar之類的,標題欄會被頂上去,解決辦法 android:fitsSystemWindows=“true”
或者這樣設置
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
View mChildView = mContentView.getChildAt(0);
if (mChildView != null) {
//注意不是設置 ContentView 的 FitsSystemWindows, 而是設置 ContentView 的第一個子 View . 預留出系統 View 的空間.
mChildView.setFitsSystemWindows(fitSystemWindows);
}

7適配全面屏:

7.1
因此建議開發者聲明 Maximum Aspect Ratio > 2 或更多。值得一提的是,如果應用的 android:resizeableActivity 已經設置爲 true,就不必設置 Maximum Aspect Ratio 了。詳見官方文檔 Declaring maximum aspect ratio。
http://www.easemob.com/news/973

7.2 全面屏介紹
https://developer.huawei.com/consumer/cn/devservice/doc/50111
7.2.1全面屏定義
普通屏:縱橫比爲16:9,如1080x1920、1440x2560等,其比值爲1.78,全面屏手機出現之前,Android中默認的最大屏幕縱橫比(maximum aspect ratio)爲1.86,即能夠兼容16:9的屏幕。

全面屏:屏幕比例超過1.86的屏幕,比如:17:9、18:9、19:9、19.5:9 等這些比例的屏幕都是全面屏。

7.2.2 全面屏機型
機型 屏幕縱橫比 ratio_float
Mate10 pro 18:9 2.0
LG G6 18:9 2.0
Samsung Galaxy S8 18.5:9 2.06
Essential Phone 19:10 1.9
小米MIX
17:9 1.89
iPhone X 19.5:9 2.17

8
華爲手機底部虛擬導航欄遮擋佈局解決方案
8.1 發現有虛擬導航的時候,改變佈局高度
activity.getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, getNavigationBarHeight(activity));

public static int getNavigationBarHeight(Context context) {
boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
if (!hasMenuKey && !hasBackKey) {
Resources resources = context.getResources();
int resourceId = resources.getIdentifier(“navigation_bar_height”, “dimen”, “android”);//獲取NavigationBar的高度
int height = resources.getDimensionPixelSize(resourceId);
return height;
} else {
return 0;
}
}

8.2
讓底部狀態欄透明,不過這種會讓導航欄圖標顏色變白(不美觀)
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章