最近在做有關(guān)于安卓的登陸界面刀疙,這里就涉及了一些沉浸式的效果。打算邊做研究邊寫博客湃交,首先第一個遇到的就是狀態(tài)欄的顏色改變的挑戰(zhàn)熟空。
看了一些博客和官方的文檔,這里又分為三個部分搞莺。
一:4.4以下的安卓手機(jī)
4.4以下的手機(jī)并不支持狀態(tài)欄的改變息罗,這里提一下就好。
二:5.0以上的安卓手機(jī)
在5.0以上才沧,谷歌推出了一個UI設(shè)計方式叫做material design迈喉,這里面提及到了沉浸式效果绍刮,也給出了幾種方法去進(jìn)行實現(xiàn)。
1.代碼實現(xiàn)
5.0以上我們直接獲取窗口然后進(jìn)行set就可以了挨摸。
public static void setStatusBarColorToLOLLIPOP(Activity activity, int statusColor){
Window window = activity.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(statusColor);
}
這里有個坑是孩革,如果你是設(shè)定狀態(tài)欄為白色的話,狀態(tài)欄文字也是白色的油坝,這回導(dǎo)致看不到內(nèi)容嫉戚,所以我們需要修改一下狀態(tài)欄文字的顏色。
這里也分為幾種方式(根據(jù)別人博客收集澈圈,感謝互聯(lián)網(wǎng)的資料共享)
分為谷歌原生以及小米和魅族手機(jī)的方式彬檀。
原生方式如下:
/**
* 狀態(tài)欄的修改顏色,實際上就是改變decorview的狀態(tài)位
* @param activity
* @param dark
*/
private static void setAndroidNativeLightStatusBar(Activity activity, boolean dark) {
View decor = activity.getWindow().getDecorView();
if (dark) {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
}
這里實際上是DecorView的標(biāo)志位進(jìn)行切換:
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR和
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
dark標(biāo)識是否為黑瞬女,如果為黑則從LIGHT轉(zhuǎn)到下面窍帝。亮則相反。
在其他博客中我看到說這個方式其實是有個bug的诽偷,因FLAG_LAYOUT_FULLSCREEN這個標(biāo)識是一只會攜帶著的坤学,所以會出現(xiàn)默認(rèn)界面會變成全屏模式。需要進(jìn)行設(shè)置(但是目前我的登陸ui并沒有出現(xiàn)這樣的問題报慕。所以暫時先放出他的解決方案)
此處放出對方的博客鏈接:http://www.reibang.com/p/7392237bc1de(接下來的大部分代碼都由此而來深浮。)
需要在根布局中設(shè)置FitsSystemWindows屬性為true,或在基類的 process方法中加入如下的代碼眠冈。
@Override
protected void process(Bundle savedInstanceState) {
// 華為,OPPO機(jī)型在StatusBarUtil.setLightStatusBar后布局被頂?shù)綘顟B(tài)欄上去了
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View content = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
if (content != null && !isUseFullScreenMode()) {
content.setFitsSystemWindows(true);
}
}
}
android:fitsSystemWindows="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);//狀態(tài)欄透明且黑色字體
} else {
extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字體
}
result = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && RomUtils.isMiUIV7OrAbove()) {
//開發(fā)版 7.7.13 及以后版本采用了系統(tǒng)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_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
}
} catch (Exception e) {
}
}
return result;
}
這里是開發(fā)版 7.7.13以下的MIUI蜗顽,沒有使用系統(tǒng)的API布卡,所以會出現(xiàn)這個問題。
大致思路通過反射獲取Miui的類雇盖,然后再通過這個類進(jìn)行方法的使用忿等。
三:魅族手機(jī)的思路同樣和小米一樣,通過反射獲取崔挖。
private static boolean setFlymeLightStatusBar(Activity activity, boolean dark) {
boolean result = false;
if (activity != null) {
try {
WindowManager.LayoutParams lp = activity.getWindow().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);
activity.getWindow().setAttributes(lp);
result = true;
} catch (Exception e) {
}
}
return result;
}
至于判斷手機(jī)型號的方法則不討論了贸街,網(wǎng)上可進(jìn)行查找。
4.4-5.0安卓手機(jī)適配
思路:修改狀態(tài)欄為透明之后狸相,在布局中添加一個背景為期望色值的View來作為狀態(tài)欄的填充匾浪。
當(dāng)然,以下代碼是簡略的實現(xiàn)卷哩。
/**
* 4.4 - 5.0屏幕狀態(tài)欄顏色修改
* 思路:修改狀態(tài)欄為透明之后蛋辈,在布局中添加一個背景為期望色值的View來作為狀態(tài)欄的填充。
* @param activity
* @param statusColor
*/
public static void setStatusBarColor(Activity activity, int statusColor){
Window window = activity.getWindow();
/*設(shè)置Window為全透明
*Field requires API level 19 (current min is 17)
*/
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
//獲取狀態(tài)欄高度
int statusBarHeight = getStatusBarHeight(activity);
//如果已經(jīng)存在假狀態(tài)欄則移除,防止重復(fù)添加
removeFakeStatusBarViewIfExist(activity);
//添加一個View來作為狀態(tài)欄的填充
ViewGroup decorViewGroup = (ViewGroup) window.getDecorView();
View statusBarView = new View(window.getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, statusBarHeight);
params.gravity = Gravity.TOP;
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(statusColor);
decorViewGroup.addView(statusBarView);
}
這里會出現(xiàn)一個問題冷溶,就是有條大黑邊渐白。