package com.github.miao1007.animewallpaper.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Created by leon on 10/31/15.
*/
public final class StatusBarUtils {
private final boolean lightStatusBar;
//透明且背景不占用控件的statusbar,这里估且叫做沉浸
private final boolean transparentStatusBar;
private final boolean transparentNavigationbar;
private final Window window;
private final View actionBarView;
private final int current = Build.VERSION.SDK_INT;
private StatusBarUtils(Window window, boolean lightStatusBar, boolean transparentStatusBar,
boolean transparentNavigationbar, View actionBarView) {
this.lightStatusBar = lightStatusBar;
this.transparentStatusBar = transparentStatusBar;
this.window = window;
this.transparentNavigationbar = transparentNavigationbar;
this.actionBarView = actionBarView;
}
public static boolean isLessKitkat() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT;
}
public static Builder from(Activity activity) {
return new Builder().setWindow(activity);
}
public static Builder from(Dialog dialog) {
return new Builder().setWindow(dialog);
}
public static Builder from(Window window) {
return new Builder().setWindow(window);
}
/**
* Default status dp = 24 or 25
* mhdpi = dp * 1
* hdpi = dp * 1.5
* xhdpi = dp * 2
* xxhdpi = dp * 3
* eg : 1920x1080, xxhdpi, => status/all = 25/640(dp) = 75/1080(px)
*
* don't forget toolbar's dp = 48
*
* @return px
*/
@IntRange(from = 0, to = 75) public static int getStatusBarOffsetPx(Context context) {
if (isLessKitkat()) {
return 0;
}
Context appContext = context.getApplicationContext();
int result = 0;
int resourceId =
appContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = appContext.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
@IntRange(from = 0, to = 75) public static int getNavigationBarOffsetPx(Context context) {
if (isLessKitkat()) {
return 0;
}
Context appContext = context.getApplicationContext();
int result = 0;
int resourceId =
appContext.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = appContext.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
private void processActionBar(final View v) {
if (v == null || !transparentStatusBar || isLessKitkat()) {
return;
}
v.post(new Runnable() {
@Override public void run() {
v.setPadding(v.getPaddingLeft(), v.getPaddingTop() + getStatusBarOffsetPx(v.getContext()),
v.getPaddingRight(), v.getPaddingBottom());
v.getLayoutParams().height += getStatusBarOffsetPx(v.getContext());
}
});
}
/**
* 调用私有API处理颜色
*/
private void processPrivateAPI() {
try {
processFlyMe(lightStatusBar);
} catch (Exception e) {
try {
processMIUI(lightStatusBar);
} catch (Exception e2) {
//
}
}
}
private void process() {
//调用私有API处理颜色
processPrivateAPI();
processActionBar(actionBarView);
//处理4.4~5.0沉浸
if (current >= Build.VERSION_CODES.KITKAT && current < Build.VERSION_CODES.M) {
processKitkat();
} else if (current >= Build.VERSION_CODES.M) {
processM();
}
}
/**
* 处理4.4沉浸
*/
@TargetApi(Build.VERSION_CODES.KITKAT) private void processKitkat() {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
if (transparentStatusBar) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
window.setAttributes(winParams);
}
/**
* 改变小米的状态栏字体颜色为黑色, 要求MIUI6以上
* Tested on: MIUIV7 5.0 Redmi-Note3
*/
private void processMIUI(boolean lightStatusBar) throws Exception {
Class<? extends Window> clazz = window.getClass();
int darkModeFlag;
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);
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);
}
/**
* 改变魅族的状态栏字体为黑色,要求FlyMe4以上
*/
private void processFlyMe(boolean isLightStatusBar) throws Exception {
WindowManager.LayoutParams lp = window.getAttributes();
Class<?> instance = Class.forName("android.view.WindowManager$LayoutParams");
int value = instance.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON").getInt(lp);
Field field = instance.getDeclaredField("meizuFlags");
field.setAccessible(true);
int origin = field.getInt(lp);
if (isLightStatusBar) {
field.set(lp, origin | value);
} else {
field.set(lp, (~value) & origin);
}
}
@TargetApi(Build.VERSION_CODES.M) private void processM() {
if (current < Build.VERSION_CODES.M) {
return;
}
int flag = window.getDecorView().getSystemUiVisibility();
if (lightStatusBar) {
/**
* 改变字体颜色
* see {@link <a href="https://developer.android.com/reference/android/R.attr.html#windowLightStatusBar"></a>}
*/
flag |= (WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
window.setStatusBarColor(Color.TRANSPARENT);
}
if (transparentStatusBar) {
flag |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
window.setStatusBarColor(Color.TRANSPARENT);
}
if (transparentNavigationbar) {
flag |= (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
window.setNavigationBarColor(Color.TRANSPARENT);
}
window.getDecorView().setSystemUiVisibility(flag);
}
final public static class Builder {
private Window window;
private boolean lightStatusBar = false;
private boolean transparentStatusbar = false;
private boolean transparentNavigationbar = false;
private View actionBarView;
public Builder setActionbarView(@Nullable View actionbarView) {
this.actionBarView = actionbarView;
return this;
}
private Builder setWindow(@NonNull Window Window) {
this.window = Window;
return this;
}
private Builder setWindow(@NonNull Activity activity) {
this.window = activity.getWindow();
return this;
}
private Builder setWindow(@NonNull Dialog dialog) {
this.window = dialog.getWindow();
return this;
}
public Builder setLightStatusBar(boolean lightStatusBar) {
this.lightStatusBar = lightStatusBar;
return this;
}
public Builder setTransparentStatusbar(boolean transparentStatusbar) {
this.transparentStatusbar = transparentStatusbar;
return this;
}
public Builder setTransparentNavigationbar(boolean transparentNavigationbar) {
this.transparentNavigationbar = transparentNavigationbar;
return this;
}
public void process() {
new StatusBarUtils(window, lightStatusBar, transparentStatusbar, transparentNavigationbar,
actionBarView).process();
}
}
}