安卓透明StatusBar及設(shè)置文字圖標(biāo)顏色

自定義狀態(tài)欄的實(shí)現(xiàn)一般分為兩種方式:
1)將布局內(nèi)容延展至狀態(tài)欄;
2)使用沉浸式狀態(tài)欄
。

由于大部分android系統(tǒng)狀態(tài)欄采用黑色背景,白色的字體圖標(biāo)。這導(dǎo)致以上兩種實(shí)現(xiàn)方式存在一個(gè)共性問題,即狀態(tài)欄背景顏色定義為白色等淺色調(diào)時(shí),這導(dǎo)致狀態(tài)欄顯示白屏。

該問題只能通過更改狀態(tài)欄字體圖標(biāo)的顏色來解決,但存在兼容性問題。目前只有MIUI6及以上、魅族以及android 6.0以上可以設(shè)置。

注意,測(cè)試手機(jī)MX5,android系統(tǒng)5.1,flyme6.0.2.0A,在設(shè)置狀態(tài)欄顏色setStatusBar后,系統(tǒng)會(huì)根據(jù)statusbar的色調(diào)自動(dòng)變更狀態(tài)欄字體圖標(biāo)顏色。

一、布局內(nèi)容延展至狀態(tài)欄

注意:android 4.4及以上可以實(shí)現(xiàn)該功能。

實(shí)現(xiàn)該功能最簡(jiǎn)單粗暴的方法是使用屬性windowTranslucentStatus="true",該屬性使布局內(nèi)容得以延伸到狀態(tài)欄和導(dǎo)航欄所在的空間,形成類似全屏的視覺效果。但使用該方法后會(huì)引入一些問題。

該屬性的java設(shè)置方法為:

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS );
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS );
1、界面布局上部分和狀態(tài)欄重合。

該問題的解決方案:
1) 界面根布局設(shè)置屬性fitsSystemWindow=true,該屬性使得屏幕上的可布局空間位于狀態(tài)欄下方與導(dǎo)航欄上方。但該屬性只對(duì)簡(jiǎn)單布局有效,且可能引入EditText輸入時(shí)軟鍵盤遮擋光標(biāo)的問題;

一個(gè)高票workround解決方案如下:

//調(diào)用方式
//To use this class, simply invoke assistActivity() on an Activity that already has its content view set. 

//實(shí)現(xiàn)方法
public class AndroidBug5497Workaround {

    // For more information, see https://code.google.com/p/android/issues/detail?id=5497
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

    public static void assistActivity (Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private AndroidBug5497Workaround(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    }

}

2)手動(dòng)在布局中添加StatusBar的空間,設(shè)置一個(gè)25dp的view來搞定。注意,可能不同版本的StatusBar高度不同,需要用dimen來設(shè)備
3)代碼設(shè)置根布局的margin;topMagin的值等于狀態(tài)欄的高度。缺點(diǎn)是每個(gè)界面布局需要使用統(tǒng)一的布局格式

//獲取狀態(tài)欄高度
public static int getStatusBarHeight(Context context)
{
    int result = 0;
    int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0)
    {
        result = context.getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

該方案在面對(duì)淺色狀態(tài)布局內(nèi)容時(shí),存在限制。

參考:http://blog.csdn.net/ling9400/article/details/59478358
https://www.zhihu.com/question/31468556

二、沉浸式狀態(tài)欄

如果不需要支持 4.4,建議使用 statusBarColor
如果需要支持 4.4,建議 4.4 使用 windowTranslucentStatus;5.x 使用 statusBarColor/colorPrimaryDark

方案如下

//設(shè)置狀態(tài)欄顏色
1、activity.getWindow().setStatusBarColor(int color)

//因?yàn)?FLAT_LAYOUT_STABLE 和 FLAG_LAYOUT_FULLSCREEN 是伴隨 translucentStatus 自動(dòng)設(shè)置的,v21 上需要手動(dòng)設(shè)置
2、activity.getWindow()
    .getDecorView()
    .setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

//調(diào)整view的高度,可以動(dòng)態(tài)設(shè)置為StatusBar 的 Height;或者設(shè)置padding
3、<android.support.v7.widget.Toolbar
    android:background="?attr/colorPrimary"
    android:minHeight="?attr/actionBarSize"
    android:elevation="@dimen/space_small"
    android:paddingTop="@dimen/status_bar_height/>

 //dimens.xml
<dimen name="status_bar_height">25dp</dimen>

//values-v23/dimens.xml
<dimen name="status_bar_height">24dp</dimen>

//小米沉浸式狀態(tài)欄
https://dev.mi.com/doc/p=4769/ //

//魅族沉浸式狀態(tài)欄
http://open-wiki.flyme.cn/index.php?title=%E7%8A%B6%E6%80%81%E6%A0%8F%E5%8F%98%E8%89%B2

三、深色狀態(tài)欄方案

注意,改變狀態(tài)欄文字圖標(biāo)顏色的代碼,需要在主線程運(yùn)行。

關(guān)于機(jī)型判斷,可參考一下文章:
//魅族機(jī)型判斷
http://blog.csdn.net/sslinp/article/details/50535188

////如何判斷小米系統(tǒng)
https://dev.mi.com/doc/?p=254

一、魅族手機(jī)設(shè)置

//注意該方法需要在setStatusColor調(diào)用前設(shè)置,否則系統(tǒng)狀態(tài)欄顏色變?yōu)楹谏?public static boolean setMeiZuStatusBarDarkIcon(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) {
                Log.e("MeiZu", "setStatusBarDarkIcon: failed");
            }
        }
        return result;
    }

參考:魅族官網(wǎng)解決方案flyme4+

二、小米手機(jī)方案

    //MIUI 6.0以上
    public static boolean setMIUIStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        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);//狀態(tài)欄透明且黑色字體
                }else{
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字體
                }
                result=true;
            }catch (Exception e){

            }

            //在新的 MIUI 版本(即基于 Android 6.0 ,開發(fā)版 7.7.13 及以后版本).使用新方案
            //參考http://www.miui.com/thread-8946673-1-1.html
            //https://dev.mi.com/console/doc/detail?pId=1159
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (dark) {
                    int flag = window.getDecorView().getSystemUiVisibility() |
                            View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
                    window.getDecorView().setSystemUiVisibility(flag);
                } else {
                    int flag = window.getDecorView().getSystemUiVisibility() &
                            ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
                    window.getDecorView().setSystemUiVisibility(flag);
                }
            }
        }
        return result;
    }

三、android M(6.0)及以上方案

//compileSdkVersion為6.0及以上
    public boolean setStatusBarLightMode(Activity activity, boolean isFontColorDark) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (isFontColorDark) {
                // 沉浸式
                //                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                //非沉浸式
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            } else {
                //非沉浸式
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            }
            return true;
        }
        return false;
    }

參考: 小米官網(wǎng)解決方案MIUI6+
其他:
http://www.voidcn.com/blog/wds1181977/article/p-6167721.html
http://blog.csdn.net/jo__yang/article/details/51456126

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,040評(píng)論 25 709
  • 前言 首先請(qǐng)大家看幾張圖: 以上的效果,一般我們統(tǒng)稱為沉浸式狀態(tài)欄。其實(shí),這種叫法不是很準(zhǔn)確,而且也沒有沉浸式狀態(tài)...
    宇是我閱讀 4,194評(píng)論 2 28
  • 概念 全屏模式 變色狀態(tài)欄模式 背景全屏+變色狀態(tài)欄模式 圖片全屏+變色狀態(tài)欄模式 ContentView: ac...
    我不是死胖子閱讀 1,700評(píng)論 0 2
  • 同學(xué)在朋友圈轉(zhuǎn)《有幾個(gè)當(dāng)媽的不是神經(jīng)病》,我復(fù)她,你還早,等娃娃到兩歲多,更難對(duì)付。她回我,你是深有體會(huì)。 放下手...
    容止若思閱讀 190評(píng)論 0 0
  • 鎊美4H上升通道上軌空,日線前期三角形破位處的壓力。
    瑞祺閱讀 243評(píng)論 0 0

友情鏈接更多精彩內(nèi)容