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方法;
getWindow().setStatusBarColor(getResources().getColor(R.color.colorAccent));
注意:在使用的时候会提示该方法是在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.0+
//直接调用系统提供的方法 setStatusBarColor
activity.getWindow().setStatusBarColor(color);
}else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){
//android4.4-android5.0
//设置成全屏
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(0);
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 = -1;
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方法;
getWindow().setNavigationBarColor(getResources().getColor(R.color.colorAccent));
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=0;
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>0||h>0;
}
获取底部导航栏的高度和上面获取导航栏的高度差不多;
/**
* 获取底部导航栏高度
* @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效果: