Android 6.0 以上實(shí)現(xiàn)狀態(tài)欄白底黑字 「白色標(biāo)題欄 App 享受 iOS 般的沉浸體驗(yàn)」
前言: 其實(shí)我挺不愿意起這個(gè)標(biāo)題的,為什么 Android 非要做的跟 iOS 一樣, 但是對于狀態(tài)欄這個(gè)顏色這個(gè)需求我想還是有必要像 iOS 學(xué)習(xí)一下,畢竟 5.0 之前,狀態(tài)欄萬年黑色的樣子的確和大部分 App 的主題樣式有點(diǎn)不太融合, 但是最近受到產(chǎn)品的大哥在玩小密圈,看到他們的狀態(tài)欄效果,所以讓我也實(shí)現(xiàn)下也這樣的效果 O(∩_∩)O~。
網(wǎng)上關(guān)于「沉浸式狀態(tài)欄」「透明狀態(tài)欄」的文章 Google 一搜一大把。文章的開頭先給大家列舉一下幾個(gè)常見的實(shí)現(xiàn)方式吧:
- 如果你的 App 需要考慮 Android 4.4 版本的狀態(tài)欄顏色改變,那么就請移步這個(gè)第三方庫 SystemBarTint;
- 如果你的 App 僅需要考慮 Android 5.0 版本以上的狀態(tài)欄顏色適配,這里推薦一個(gè)簡單實(shí)用的實(shí)現(xiàn)方式,薄荷TOOLBAR(ACTIONBAR)的適配方案
薄荷公司 statueBar 的適配方案
之前我們的 App 剛開始搭建的時(shí)候采用的是,薄荷公司的狀態(tài)欄適配方式,主要思路是:
-
設(shè)置主題狀態(tài)欄背景透明,在 values-v19 的文件夾下新建一個(gè) style 文件,
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">true</item> </style>
-
設(shè)置并在該文件夾下添加 dimens 文件,設(shè)置 toolbar padding 為24dp
<dimen name="toolbar_padding_top">24dp</dimen>
-
在 values 文件夾設(shè)置同名 dimens 的值為 0dp
<dimen name="toolbar_padding_top">0dp</dimen>
該屬性需要在你的 Toolbar 中設(shè)置一下 paddingTop 并引用該 dimens 值,這樣在不同版本的手機(jī)上,就會自動選擇不同的值。
-
并在app中的 baseActivity 類中實(shí)現(xiàn)如下代碼:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.activity_base); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes(); localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags); } }
在代碼中實(shí)現(xiàn)上述代碼是因?yàn)閲鴥?nèi)有些 rom 如果單純在 style 文件中設(shè)置
windowTranslucentStatus
可能導(dǎo)致設(shè)置無效。所以在 Activity 中再次設(shè)置一遍 。 最后不要忘了在 清單文件中應(yīng)用你設(shè)置的主題。
上述為薄荷公司的實(shí)現(xiàn)方式如果有不明白的地方請看「stormzhang」的博客,薄荷TOOLBAR(ACTIONBAR)的適配方案
小米手機(jī),魅族手機(jī)狀態(tài)欄顏色適配
國內(nèi)某些知名手機(jī)品牌,對原生 rom 進(jìn)行深度優(yōu)化然后改造了屬于自己的 rom,但是這樣對開發(fā)者來說可能就是一定程度上的災(zāi)難,比如 小米和魅族 rom 已經(jīng)自己內(nèi)置修改狀態(tài)欄為白底透明的字體顏色為白色的,所以對于上述狀態(tài)欄適配的話:如果 app 的標(biāo)題欄是深色主題的還好,如果是淺色的如我們的 app 是白色的那么就會出現(xiàn),進(jìn)了我們 app 還想看時(shí)間,哈哈做夢吧。幸運(yùn)的是小米和魅族都給了對應(yīng)的解決方案,通過解決方案可以修改 app 內(nèi)部的狀態(tài)欄可以設(shè)置為黑色字體:
public static boolean MIUISetStatusBarLightMode(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) {
}
}
return result;
}
對應(yīng)魅族的修改方法是:
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;
}
最后我們需要在我們的BaseActivity 中加入適配代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_base);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}
MIUISetStatusBarLightMode(this.getWindow(), true);
FlymeSetStatusBarLightMode(this.getWindow(), true);
}
小米上實(shí)現(xiàn)效果:
看起來還不錯(cuò),但是之后看到在華為手機(jī) 5.0 以上的效果是這樣的:
這個(gè)可能就是各個(gè)rom優(yōu)化完以后的效果,作為一個(gè)精益求精的開發(fā)者,我認(rèn)為華為上這個(gè)效果實(shí)在是太丑了。那么有沒有更好的實(shí)現(xiàn)方案呢?
期間試了網(wǎng)上各種5.0 以上的狀態(tài)欄適配效果,在華為手機(jī)上都不太理想,大家都知道 Android 6.0 系統(tǒng)已經(jīng)發(fā)布近兩年時(shí)間了,國內(nèi)各個(gè)應(yīng)用廠商,也開始適配新的機(jī)型,所以我們考慮的是,為了達(dá)到不同手機(jī)上效果一致,所以就不采用任何第三方的方案了:『利用系統(tǒng)自帶的api,實(shí)現(xiàn) Android 6.0 以上的狀態(tài)欄適配』
利用系統(tǒng)自帶的api,實(shí)現(xiàn) Android 6.0 以上的狀態(tài)欄適配
因?yàn)橹安捎昧吮『晒镜倪m配方法,要修改的話就需要在最好的改動的情況下進(jìn)行修改:
修改 dimens 文件夾的
<dimen name="toolbar_padding_top">0dp</dimen>
均為 0dp;-
修改主題樣式 將values-v19 修改為 values-v23 并且在styles 文件中就修改主題為:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:colorPrimaryDark">@color/title_color</item> <item name="android:colorPrimary">@color/white</item> <item name="android:colorAccent">@color/white</item> <item name="windowNoTitle">true</item> </style>
-
修改 BaseActivity 中的為:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 系統(tǒng) 6.0 以上 狀態(tài)欄白底黑字的實(shí)現(xiàn)方法 this.getWindow() .getDecorView() .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); MIUISetStatusBarLightMode(this.getWindow(), true); FlymeSetStatusBarLightMode(this.getWindow(), true); }
運(yùn)行一下看下在華為手機(jī)上的效果:
Perfect! 這個(gè)效果老板和UI都很滿意,問題也圓滿解決了,我怕其他機(jī)型會有意外于是跑遍了公司所有的測試機(jī)和同事手機(jī)效果都一致,所以還算可以吧。
總結(jié)
個(gè)人認(rèn)為,谷歌官方不推薦做的如果你非要做,要么就需要踩很多坑,要么最終實(shí)現(xiàn)了效果也不是很理想,所以如果你的 app ,是像我們一樣的白色狀態(tài)欄的主題,那么就可以試一試我們這個(gè)方法。