android5.0推出了沉浸式狀态欄的效果,讓android狀态欄可以輕松的改變顔色,大大提升app的一個視覺效果,相信android開發者們都已經早就接觸并實作過該效果了,最近剛好有時間,将自己的一個實作記錄下來;沉浸式效果在android5.0+上面實作起來還是比較簡單,但是要在android4.4-android5.0上面實作的還是要費點事情,目前還沒有看到android4.4以下實作了該效果,是以在開發中隻需做android5.0+和android4.4-android5.0一個相容;
android5.0+沉浸式效果的實作
方法一:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorAccent</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
修改colorPrimaryDark的顔色就可以實作沉浸式的效果,不過需要注意的是修改colorPrimaryDark的顔色意味着所有的頁面都是修改的顔色,如果某個頁面想實作不一樣的沉浸式效果,需要做特别處理;
方法二:
調用系統的setStatusBarColor方法;
注意:在使用的時候會提示該方法是在api21才會有;
方法三:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimary</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:statusBarColor">@color/colorAccent</item>
</style>
在樣式裡面添加android:statusBarColor,同樣android:statusBarColor是在api21以後才會有,所有要建立一個values-v21的檔案,并添加樣式;
不管哪種方法,在android5.0+上面基本上一句代碼就可以實作沉浸式的效果,但是當你把上面這些代碼運作到android5.0以下的手機上的時候什麼效果都不會有,是以要在上面的基礎上做相應的相容,下面就寫下如果去相容android4.4到android5.0;
對于android4.4到android5.0的思路是:首先把他弄成全屏,在狀态欄的部分加一個布局
/**
* 設定狀态欄顔色
* @param activity 對應的activity
* @param color 設定的顔色
*/
public static void setStatusBarColor(Activity activity,int color){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
//android5+
//直接調用系統提供的方法 setStatusBarColor
activity.getWindow().setStatusBarColor(color);
}else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){
//android4-android5
//設定成全屏
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//在狀态欄的部分添加一個布局
View view=new View(activity);
ViewGroup.LayoutParams params=new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusBarHeight(activity));
view.setLayoutParams(params);
view.setBackgroundColor(color);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
decorView.addView(view);
//擷取activity中setContentView布局的根布局
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
View childAt = contentView.getChildAt();
childAt.setFitsSystemWindows(true);
}
}
在擷取狀态欄高度的時候可以通過反射擷取,也可以通過另外一種方式擷取;
方式一:
/**
* 擷取狀态欄的高度
* @param activity 對應的activity
* @return 狀态欄的高度
*/
private static int getStatusBarHeight(Activity activity) {
Resources resources = activity.getResources();
int identifier = resources.getIdentifier("status_bar_height", "dimen", "android");
return resources.getDimensionPixelOffset(identifier);
}
方式二(反射):
/**
* 反射擷取狀态欄高度
* @param context 上下文
* @return 狀态欄高度
*/
private static int getStatusBarHeight(Activity context){
// 反射手機運作的類:android.R.dimen.status_bar_height.
int statusHeight = -;
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
String heightStr = clazz.getField("status_bar_height").get(object).toString();
int height = Integer.parseInt(heightStr);
//dp--->px
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}
這樣子沉浸式狀态欄效果就實作了:
android6.0效果:

android4.4.2效果:
底部導航欄沉浸式效果的實作和上面的實作大緻是一樣的;
android5.0+的實作:
方法一:
建立一個values-v21的檔案,在style樣式中添加android:navigationBarColor
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimary</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:navigationBarColor">@color/colorAccent</item>
</style>
方法二:
調用系統的setNavigationBarColor方法;
android4.4-android5.0的相容:
在布局檔案添加一個view,設定虛拟導航欄為透明,設定view的高度為底部導航欄的高度,并設定view的顔色;
/**
* 設定底部導航顔色
* @param activity 上下文
* @param color 設定的顔色
* @param view 底部的view
*/
public static void setNavigationColor(Activity activity,int color,View view){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
//android5.0+
//直接調用系統提供的方法 setStatusBarColor
activity.getWindow().setNavigationBarColor(color);
}else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){
//android4.4-android5.0
if(view!=null){
//設定成全屏
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
//判斷底部虛拟導航欄是否存在(或者開啟)
if(hasNavigationBarShow(activity.getWindowManager())){
ViewGroup.LayoutParams p = view.getLayoutParams();
p.height+=getNavigationBarHeight(activity);
view.setLayoutParams(p);
view.setBackgroundColor(color);
}else{
ViewGroup.LayoutParams p = view.getLayoutParams();
p.height=;
view.setLayoutParams(p);
}
}
}
}
這裡需要注意的是要判斷底部導航欄是否存在,在有些手機上是沒有底部導航欄,有些手機上即使有底部導航欄,也可以設定關閉底部導航欄,在設定的時候需要判斷;
/**
* 判斷底部虛拟導航欄是否存在(打開)
* @param windowManager
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
private static boolean hasNavigationBarShow(WindowManager windowManager) {
Display display = windowManager.getDefaultDisplay();
DisplayMetrics outMetrics=new DisplayMetrics();
//擷取整個螢幕的高度
display.getRealMetrics(outMetrics);
int heightPixels = outMetrics.heightPixels;
int widthPixels = outMetrics.widthPixels;
//擷取内容展示部分的高度
outMetrics=new DisplayMetrics();
int heightPixels1 = outMetrics.heightPixels;
int widthPixels1 = outMetrics.widthPixels;
int h=heightPixels-heightPixels1;
int w=widthPixels-widthPixels1;
return w>||h>;
}
擷取底部導航欄的高度和上面擷取導航欄的高度差不多;
/**
* 擷取底部導航欄高度
* @param activity 上下文
* @return 底部導航欄高度
*/
private static int getNavigationBarHeight(Activity activity) {
Resources resources = activity.getResources();
int identifier = resources.getIdentifier("navigation_bar_height", "dimen", "android");
return resources.getDimensionPixelOffset(identifier);
}
這樣就實作底部導航欄沉浸式效果了;
android6.0效果:
android4.4.2效果:
源碼位址:
http://download.csdn.net/download/wangwo1991/9928577