content: /*
   * Copyright  2017 [AllenCoder]
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.allen.apputils;
  
  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 AllenCoder
   */
  public final class StatusBarUtils {
  
      boolean lightStatusBar;
      //透明且背景不占用控件的statusbar，这里估且叫做沉浸
      boolean transparentStatusBar;
      Window window;
      View actionBarView;
  
      private StatusBarUtils(Window window, boolean lightStatusBar, boolean transparentStatusBar,
                             View actionBarView) {
          this.lightStatusBar = lightStatusBar;
          this.transparentStatusBar = transparentStatusBar;
          this.window = window;
          this.actionBarView = actionBarView;
      }
  
      public static boolean isKitkat() {
          return Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT;
      }
  
      public static boolean isLessKitkat() {
          return Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT;
      }
  
      public static boolean isMoreLollipop() {
          return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
      }
  
      public static Builder from(Activity activity) {
          return new StatusBarUtils.Builder().setWindow(activity);
      }
  
      public static Builder from(Dialog dialog) {
          return new StatusBarUtils.Builder().setWindow(dialog);
      }
  
      public static Builder from(Window window) {
          return new StatusBarUtils.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)
       * <p>
       * 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;
      }
  
      public 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处理颜色
       */
      public void processPrivateAPI() {
          processFlyMe(lightStatusBar);
          processMIUI(lightStatusBar);
      }
  
      public void process() {
          int current = Build.VERSION.SDK_INT;
          //处理4.4沉浸
          if (current == Build.VERSION_CODES.KITKAT) {
              processKitkat();
          }
          //6.0处理沉浸与颜色，5.0只可以处理沉浸(不建议用白色背景)
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
              processLollipopAbove();
          }
          //调用私有API处理颜色
          processPrivateAPI();
          processActionBar(actionBarView);
      }
  
      /**
       * 处理4.4沉浸
       */
      @TargetApi(Build.VERSION_CODES.KITKAT)
      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
       */
      void processMIUI(boolean lightStatusBar) {
          Class<? extends Window> clazz = window.getClass();
          try {
              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);
          } catch (Exception ignored) {
  
          }
      }
  
      /**
       * 改变魅族的状态栏字体为黑色，要求FlyMe4以上
       */
      private void processFlyMe(boolean isLightStatusBar) {
          WindowManager.LayoutParams lp = window.getAttributes();
          try {
              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);
              }
          } catch (Exception ignored) {
              //
          }
      }
  
      /**
       * 处理Lollipop以上
       * Lollipop可以设置为沉浸，不能设置字体颜色(所以白色背景会很丑)
       * M(API23)可以设定
       */
      @TargetApi(Build.VERSION_CODES.LOLLIPOP)
      void processLollipopAbove() {
          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);
          }
          if (transparentStatusBar) {
              //改变字体颜色
              flag |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
          }
          window.getDecorView().setSystemUiVisibility(flag);
          window.setStatusBarColor(Color.TRANSPARENT);
      }
  
      final public static class Builder {
          private Window window;
          private boolean lightStatusBar = false;
          private boolean transparentStatusbar = 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 void process() {
              new StatusBarUtils(window, lightStatusBar, transparentStatusbar, actionBarView).process();
          }
      }
  }
  