本文是用于设配SDK4.4到5.0的沉浸式导航栏适配(4.4下面的实现不了沉浸式),上次说到适配沉浸式状态栏时,为DecorView添加一个View可以是实现,导航栏也同样,但是不是所有手机都有导航栏,所以我们先要判断手机有没有导航栏
代码语言:javascript
复制 public static boolean hasNavigationBar(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
//获取物理屏幕的分辨率
DisplayMetrics realMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getRealMetrics(realMetrics);
//获取屏幕的分辨率(不含导航栏)
DisplayMetrics contentMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(contentMetrics);
//如果竖屏状态下,物理屏幕的高度比内容屏幕的高度高,则含有导航栏,
//同样,横屏状态下,物理屏幕的宽度比内容屏幕的宽度高,则含有导航栏
int h = realMetrics.heightPixels - contentMetrics.heightPixels;
int w = realMetrics.widthPixels - contentMetrics.widthPixels;
return h > 0 || w > 0;
}
然后获取NavigationBar的高度
代码语言:javascript
复制 //使用运行过程中的资源文件
private static int getNavigationBarHeight(Context context) {
int statusBarHeight = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (statusBarHeight > 0) {
return statusBarHeight;
}
//上面方法获取不到的话,使用反射资源获取
return getNavigationBarHeightByAndroid(context, "com.android.internal.R$dimen", "navigation_bar_height", 48);
}
private static int getNavigationBarHeightByAndroid(Context context, String className, String fieldName, int defValue) {
try {
//获取class
Class aClass = Class.forName(className);
//获取实例
Object o = aClass.newInstance();
Field field = aClass.getField(fieldName);
int id = Integer.parseInt(field.get(o).toString());
return context.getResources().getDimensionPixelOffset(id);
} catch (Exception e) {
return defValue;
}
}
然后使用之前的套路
代码语言:javascript
复制 private static final int FAKE_NAVIGATION_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view;
/**
* 设置导航栏颜色
*
* @param activity 需要设置的activity
* @param color 导航栏颜色值
* @param statusBarAlpha 导航栏透明度
*/
public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {
if (!hasNavigationBar(activity)) {//没有导航栏直接返回
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
activity.getWindow().setNavigationBarColor(calculateNavigationColor(color, statusBarAlpha));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeNavigationBarView = decorView.findViewById(FAKE_NAVIGATION_BAR_VIEW_ID);
if (fakeNavigationBarView != null) {
if (fakeNavigationBarView.getVisibility() == View.GONE) {
fakeNavigationBarView.setVisibility(View.VISIBLE);
}
fakeNavigationBarView.setBackgroundColor(calculateNavigationColor(color, statusBarAlpha));
} else {
View view = createNavigationBarView(activity, color, statusBarAlpha);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(view.getLayoutParams());
params.gravity = Gravity.BOTTOM;
view.setLayoutParams(params);
decorView.addView(view);
}
}
}
/**
* 计算状态栏颜色
*
* @param color color值
* @param alpha alpha值
* @return 最终的状态栏颜色
*/
private static int calculateNavigationColor(@ColorInt int color, int alpha) {
if (alpha == 0) {
return color;
}
float a = 1 - alpha / 255f;
int red = color >> 16 & 0xff;
int green = color >> 8 & 0xff;
int blue = color & 0xff;
red = (int) (red * a 0.5);
green = (int) (green * a 0.5);
blue = (int) (blue * a 0.5);
return 0xff << 24 | red << 16 | green << 8 | blue;
}
/**
* 生成一个和状态栏大小相同的半透明矩形条
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param alpha 透明值
* @return 状态栏矩形条
*/
private static View createNavigationBarView(Activity activity, @ColorInt int color, int alpha) {
// 绘制一个和状态栏一样高的矩形
View statusBarView = new View(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getNavigationBarHeight(activity));
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(calculateNavigationColor(color, alpha));
statusBarView.setId(FAKE_NAVIGATION_BAR_VIEW_ID);
return statusBarView;
}