沉浸式含義
首先先明確一點沉浸式狀態(tài)欄的說法并不準確账千,沉浸式是Android4.4推出的一種模式耍攘,可以使顯示系統(tǒng)消息的狀態(tài)欄(Status Bar)與最下方顯示虛擬按鍵的底部導(dǎo)航欄(Navigation Bar)被隱藏掉攘轩。
在谷歌開發(fā)文檔中對沉浸式的描述是:“系統(tǒng) UI 保持隱藏狀態(tài),即使在用戶與您的應(yīng)用或游戲交互時 - 您可以從屏幕上的任何位置(甚至在系統(tǒng)欄占據(jù)的其他位置)捕獲觸摸事件委造。這是您在應(yīng)用或游戲中創(chuàng)建更大墨闲、更加豐富和更加沉浸式的 UI 并減少視覺分散的絕佳方式》贫埽”
Android4.4沉浸式API
1颓影、沉浸式全屏模式
setSystemUiVisibility (int visibility)
看了下標記多達十來個,以下截取部分常用標記:
SYSTEM_UI_FLAG_FULLSCREEN(WindowManager.LayoutParams.FLAG_FULLSCREEN)//隱藏狀態(tài)欄懒鉴,手指在屏幕頂部往下拖動诡挂,狀態(tài)欄會再次出現(xiàn)且不會消失
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //配合SYSTEM_UI_FLAG_FULLSCREEN使用狀態(tài)欄出現(xiàn)時,不會擠壓activty的高度,隱藏狀態(tài)欄璃俗,手指在屏幕頂部往下拖動奴璃,狀態(tài)欄會再次出現(xiàn)且不會消失
SYSTEM_UI_FLAG_IMMERSIVE// 這個標記僅與SYSTEM_UI_FLAG_HIDE_NAVIGATION配合使用,在全屏模式下在狀態(tài)欄區(qū)域滑動會重新顯示狀態(tài)欄
SYSTEM_UI_FLAG_IMMERSIVE_STICKY//在全屏模式下在狀態(tài)欄區(qū)域滑動會重新顯示透明式狀態(tài)欄旧找,一會后會重新隱藏溺健,與SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM_UI_FLAG_HIDE_NAVIGATION配合產(chǎn)生效果。
SYSTEM_UI_FLAG_HIDE_NAVIGATION//隱藏導(dǎo)航欄钮蛛,手指在導(dǎo)航欄滑動鞭缭,導(dǎo)航欄會再次出現(xiàn)且不會消失
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION//配合SYSTEM_UI_FLAG_HIDE_NAVIGATION使用導(dǎo)航欄會出現(xiàn)時,不會擠壓activty的高度魏颓,隱藏導(dǎo)航欄會岭辣,手指在導(dǎo)航欄滑動,導(dǎo)航欄會再次出現(xiàn)且不會消失
SYSTEM_UI_FLAG_LAYOUT_STABLE //保持內(nèi)容主體位置不變甸饱,不隨著Systembar的隱藏顯示而偏移
2沦童、透明系統(tǒng)狀態(tài)欄
新增兩個新主題背景Theme_Holo_NoActionBar、Theme_Holo_Light_NoActionBar叹话,如果需要不應(yīng)被系統(tǒng)狀態(tài)欄覆蓋的布局部分則應(yīng)該啟用fitsSystemWindows偷遗。
對于fitsSystemWindows,官方的說法是“布爾內(nèi)部屬性驼壶,用于根據(jù)系統(tǒng)窗口(如狀態(tài)欄)調(diào)整視圖布局氏豌。如果為true,則調(diào)整此視圖的填充以為系統(tǒng)窗口留出空間热凹。僅在此視圖位于非嵌入活動中時才會生效泵喘。”默認值為false
如果需要創(chuàng)建自定義主題般妙,可將其中一個設(shè)置為父主題背景或者在樣式中添加windowTranslucentNavigation(對應(yīng)WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)與windowTranslucentStatus(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
Android5.0沉浸式API
在Android5.0開始官方提供了android:statusBarColor (對應(yīng)方法為 setStatusBarColor)纪铺,且窗口必須使用FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS繪制系統(tǒng)欄背景
不得設(shè)置FLAG_TRANSLUCENT_STATUS。
Android9.0全面屏API
Android9.0開始增加對全全面屏的適配
具體增加以下三種標記
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT(只有當(dāng)DisplayCutout完全包含在系統(tǒng)狀態(tài)欄中時碟渺,才允許窗口延伸到DisplayCutout區(qū)域顯示)
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES(該窗口始終允許延伸到屏幕短邊上的DisplayCutout區(qū)域)
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER(該窗口決不允許與DisplayCutout區(qū)域重疊)
android9.0全面屏沉浸式代碼
getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN );
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(lp);
window.setStatusBarColor(Color.TRANSPARENT);
沉浸式分析
以下沉浸式實現(xiàn)以兩種情況做分析分別式圖片沉浸式和ActionBar沉浸式
圖片沉浸式(隱藏狀態(tài)欄圖標)
圖片沉浸式的應(yīng)用相對較多最常見的例如splash頁面
Android 4.4
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().getDecorView().setSystemUiVisibility(system_ui_flag_fullscreen|system_ui_flag_hide_navigation);
Android 5.0
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().getDecorView().setSystemUiVisibility(system_ui_flag_fullscreen|system_ui_flag_hide_navigation);
同Android4.4
Android 9.0
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(lp);
getWindow().getDecorView().setSystemUiVisibility(system_ui_flag_fullscreen|system_ui_flag_hide_navigation);
Android9.0提供新標記(LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)來適配全面屏鲜锚、劉海屏等異形屏。
ActionBar沉浸式(顯示狀態(tài)欄圖標)
Android 4.4
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
使用如上代碼 所呈現(xiàn)的UI樣式為:
可以看出actionBar占住了statusBar的位置苫拍,如果statusBar上有圖標可能會與actionBar重疊烹棉,由于當(dāng)前是在Android4.4上執(zhí)行的demo,不能使用
setStatusBarColor方法怯疤。所以我們可以在actionBar增加一個與statusBar一摸一樣的View浆洗,使之呈現(xiàn)出沉浸式感覺。
具體代碼:
/**
* 創(chuàng)建一個與statusBar一樣的View
* @param color View顏色
*/
private View createStatusBarView(Activity activity, int color) {
// 繪制一個和狀態(tài)欄一樣高的矩形
View statusBarView = new View(activity);
Log.i(TAG,"statusBarHeight:"+getStatusBarHeight());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight());
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(color);
return statusBarView;
}
/**
* 獲取statusBar高度
*/
private int getStatusBarHeight(){
int height = 0;
int resourceId = getApplicationContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
height = getApplicationContext().getResources().getDimensionPixelSize(resourceId);
}
return height;
}
/**
* setFitsSystemWindows
*/
private static void setRootView(Activity activity) {
//獲取到activity_main.xml文件
ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
//如果不設(shè)置參數(shù)集峦,會使內(nèi)容顯示到狀態(tài)欄上
rootView.setFitsSystemWindows(true);
}
/**
* 創(chuàng)建barView
*/
private void createBarView(int color) {
//1伏社、創(chuàng)建與statusBar相同高度的view
View statusView = createStatusBarView(this, color);
//2抠刺、添加statusView到布局中
ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
decorView.addView(statusView);
//3、讓布局適應(yīng)屏幕
setRootView(this);
}
直接調(diào)用createBarView方法即可實現(xiàn)效果
Android 5.0
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
由于Android 5.0新增API:setStatusBarColor摘昌,直接使用即可
Android 9.0
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark))