欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android沉浸式状态栏实现

程序员文章站 2024-02-16 23:31:34
苹果上的ui基本上都是这个效果,然而android机上的顶部状态栏总是和app的主题颜色不搭。还好如今的api19以上的版本,我们也能做出这样的效果。 第一步:...

苹果上的ui基本上都是这个效果,然而android机上的顶部状态栏总是和app的主题颜色不搭。还好如今的api19以上的版本,我们也能做出这样的效果。

Android沉浸式状态栏实现

第一步:

  // 需要setcontentview之前调用
  private void settranslucentstatus() {
  if (build.version.sdk_int >= build.version_codes.kitkat) {
    // 透明状态栏
    getwindow().addflags(
        windowmanager.layoutparams.flag_translucent_status);
    // 透明导航栏
    getwindow().addflags(
        windowmanager.layoutparams.flag_translucent_navigation);
          systemstatusmanager tintmanager = new systemstatusmanager(this);
    tintmanager.setstatusbartintenabled(true);
          // 设置状态栏的颜色 
          tintmanager.setstatusbartintresource(r.color.theme_color);
    getwindow().getdecorview().setfitssystemwindows(true);
  }
}

第二步:

为xml 的根布局添加android:fitssystemwindows=”true” 属性

第三步:systemstatusmanager

import android.annotation.suppresslint; 
import android.annotation.targetapi; 
import android.app.activity; 
import android.content.context; 
import android.content.res.configuration; 
import android.content.res.resources; 
import android.content.res.typedarray; 
import android.graphics.drawable.drawable; 
import android.os.build; 
import android.util.displaymetrics; 
import android.util.typedvalue; 
import android.view.gravity; 
import android.view.view; 
import android.view.viewconfiguration; 
import android.view.viewgroup; 
import android.view.window; 
import android.view.windowmanager; 
import android.widget.framelayout.layoutparams;

import java.lang.reflect.method;

@suppresswarnings({ “unchecked”, “rawtypes” }) 
public class systemstatusmanager 
{ 
static 
{ 
if (build.version.sdk_int >= build.version_codes.kitkat) { 
try { 
class c = class.forname(“android.os.systemproperties”); 
method m = c.getdeclaredmethod(“get”, string.class); 
m.setaccessible(true); 
snavbaroverride = (string) m.invoke(null, “qemu.hw.mainkeys”); 
} catch (throwable e) { 
snavbaroverride = null; 
} 
} 
}

/**
 * the default system bar tint color value.
 */
public static final int default_tint_color = 0x99000000;
private static string snavbaroverride;
private final systembarconfig mconfig;
private boolean mstatusbaravailable;
private boolean mnavbaravailable;
private boolean mstatusbartintenabled;
private boolean mnavbartintenabled;
private view mstatusbartintview;
private view mnavbartintview;

/**
 * constructor. call this in the host activity oncreate method after its
 * content view has been set. you should always create new instances when
 * the host activity is recreated.
 *
 * @param activity the host activity.
 */
@targetapi(19)
public systemstatusmanager(activity activity) {

  window win = activity.getwindow();
  viewgroup decorviewgroup = (viewgroup) win.getdecorview();

  if (build.version.sdk_int >= build.version_codes.kitkat) {
    // check theme attrs
    int[] attrs = {android.r.attr.windowtranslucentstatus,
        android.r.attr.windowtranslucentnavigation};
    typedarray a = activity.obtainstyledattributes(attrs);
    try {
      mstatusbaravailable = a.getboolean(0, false);
      mnavbaravailable = a.getboolean(1, false);
    } finally {
      a.recycle();
    }

    // check window flags
    windowmanager.layoutparams winparams = win.getattributes();
    int bits = windowmanager.layoutparams.flag_translucent_status;
    if ((winparams.flags & bits) != 0) {
      mstatusbaravailable = true;
    }
    bits = windowmanager.layoutparams.flag_translucent_navigation;
    if ((winparams.flags & bits) != 0) {
      mnavbaravailable = true;
    }
  }

  mconfig = new systembarconfig(activity, mstatusbaravailable, mnavbaravailable);
  // device might not have virtual navigation keys
  if (!mconfig.hasnavigtionbar()) {
    mnavbaravailable = false;
  }

  if (mstatusbaravailable) {
    setupstatusbarview(activity, decorviewgroup);
  }
  if (mnavbaravailable) {
    setupnavbarview(activity, decorviewgroup);
  }

}

/**
 * enable tinting of the system status bar.
 *
 * if the platform is running jelly bean or earlier, or translucent system
 * ui modes have not been enabled in either the theme or via window flags,
 * then this method does nothing.
 *
 * @param enabled true to enable tinting, false to disable it (default).
 */
public void setstatusbartintenabled(boolean enabled) {
  mstatusbartintenabled = enabled;
  if (mstatusbaravailable) {
    mstatusbartintview.setvisibility(enabled ? view.visible : view.gone);
  }
}

/**
 * enable tinting of the system navigation bar.
 *
 * if the platform does not have soft navigation keys, is running jelly bean
 * or earlier, or translucent system ui modes have not been enabled in either
 * the theme or via window flags, then this method does nothing.
 *
 * @param enabled true to enable tinting, false to disable it (default).
 */
public void setnavigationbartintenabled(boolean enabled) {
  mnavbartintenabled = enabled;
  if (mnavbaravailable) {
    mnavbartintview.setvisibility(enabled ? view.visible : view.gone);
  }
}

/**
 * apply the specified color tint to all system ui bars.
 *
 * @param color the color of the background tint.
 */
public void settintcolor(int color) {
  setstatusbartintcolor(color);
  setnavigationbartintcolor(color);
}

/**
 * apply the specified drawable or color resource to all system ui bars.
 *
 * @param res the identifier of the resource.
 */
public void settintresource(int res) {
  setstatusbartintresource(res);
  setnavigationbartintresource(res);
}

/**
 * apply the specified drawable to all system ui bars.
 *
 * @param drawable the drawable to use as the background, or null to remove it.
 */
public void settintdrawable(drawable drawable) {
  setstatusbartintdrawable(drawable);
  setnavigationbartintdrawable(drawable);
}

/**
 * apply the specified alpha to all system ui bars.
 *
 * @param alpha the alpha to use
 */
public void settintalpha(float alpha) {
  setstatusbaralpha(alpha);
  setnavigationbaralpha(alpha);
}

/**
 * apply the specified color tint to the system status bar.
 *
 * @param color the color of the background tint.
 */
public void setstatusbartintcolor(int color) {
  if (mstatusbaravailable) {
    mstatusbartintview.setbackgroundcolor(color);
  }
}

/**
 * apply the specified drawable or color resource to the system status bar.
 *
 * @param res the identifier of the resource.
 */
public void setstatusbartintresource(int res) {
  if (mstatusbaravailable) {
    mstatusbartintview.setbackgroundresource(res);
  }
}

/**
 * apply the specified drawable to the system status bar.
 *
 * @param drawable the drawable to use as the background, or null to remove it.
 */
@suppresswarnings("deprecation")
public void setstatusbartintdrawable(drawable drawable) {
  if (mstatusbaravailable) {
    mstatusbartintview.setbackgrounddrawable(drawable);
  }
}

/**
 * apply the specified alpha to the system status bar.
 *
 * @param alpha the alpha to use
 */
@targetapi(11)
public void setstatusbaralpha(float alpha) {
  if (mstatusbaravailable && build.version.sdk_int >= build.version_codes.honeycomb) {
    mstatusbartintview.setalpha(alpha);
  }
}

/**
 * apply the specified color tint to the system navigation bar.
 *
 * @param color the color of the background tint.
 */
public void setnavigationbartintcolor(int color) {
  if (mnavbaravailable) {
    mnavbartintview.setbackgroundcolor(color);
  }
}

/**
 * apply the specified drawable or color resource to the system navigation bar.
 *
 * @param res the identifier of the resource.
 */
public void setnavigationbartintresource(int res) {
  if (mnavbaravailable) {
    mnavbartintview.setbackgroundresource(res);
  }
}

/**
 * apply the specified drawable to the system navigation bar.
 *
 * @param drawable the drawable to use as the background, or null to remove it.
 */
@suppresswarnings("deprecation")
public void setnavigationbartintdrawable(drawable drawable) {
  if (mnavbaravailable) {
    mnavbartintview.setbackgrounddrawable(drawable);
  }
}

/**
 * apply the specified alpha to the system navigation bar.
 *
 * @param alpha the alpha to use
 */
@targetapi(11)
public void setnavigationbaralpha(float alpha) {
  if (mnavbaravailable && build.version.sdk_int >= build.version_codes.honeycomb) {
    mnavbartintview.setalpha(alpha);
  }
}

/**
 * get the system bar configuration.
 *
 * @return the system bar configuration for the current device configuration.
 */
public systembarconfig getconfig() {
  return mconfig;
}

/**
 * is tinting enabled for the system status bar?
 *
 * @return true if enabled, false otherwise.
 */
public boolean isstatusbartintenabled() {
  return mstatusbartintenabled;
}

/**
 * is tinting enabled for the system navigation bar?
 *
 * @return true if enabled, false otherwise.
 */
public boolean isnavbartintenabled() {
  return mnavbartintenabled;
}

private void setupstatusbarview(context context, viewgroup decorviewgroup) {
  mstatusbartintview = new view(context);
  layoutparams params = new layoutparams(layoutparams.match_parent, mconfig.getstatusbarheight());
  params.gravity = gravity.top;
  if (mnavbaravailable && !mconfig.isnavigationatbottom()) {
    params.rightmargin = mconfig.getnavigationbarwidth();
  }
  mstatusbartintview.setlayoutparams(params);
  mstatusbartintview.setbackgroundcolor(default_tint_color);
  mstatusbartintview.setvisibility(view.gone);
  decorviewgroup.addview(mstatusbartintview);
}

private void setupnavbarview(context context, viewgroup decorviewgroup) {
  mnavbartintview = new view(context);
  layoutparams params;
  if (mconfig.isnavigationatbottom()) {
    params = new layoutparams(layoutparams.match_parent, mconfig.getnavigationbarheight());
    params.gravity = gravity.bottom;
  } else {
    params = new layoutparams(mconfig.getnavigationbarwidth(), layoutparams.match_parent);
    params.gravity = gravity.right;
  }
  mnavbartintview.setlayoutparams(params);
  mnavbartintview.setbackgroundcolor(default_tint_color);
  mnavbartintview.setvisibility(view.gone);
  decorviewgroup.addview(mnavbartintview);
}

/**
 * class which describes system bar sizing and other characteristics for the current
 * device configuration.
 *
 */
public static class systembarconfig {

  private static final string status_bar_height_res_name = "status_bar_height";
  private static final string nav_bar_height_res_name = "navigation_bar_height";
  private static final string nav_bar_height_landscape_res_name = "navigation_bar_height_landscape";
  private static final string nav_bar_width_res_name = "navigation_bar_width";
  private static final string show_nav_bar_res_name = "config_shownavigationbar";

  private final boolean mtranslucentstatusbar;
  private final boolean mtranslucentnavbar;
  private final int mstatusbarheight;
  private final int mactionbarheight;
  private final boolean mhasnavigationbar;
  private final int mnavigationbarheight;
  private final int mnavigationbarwidth;
  private final boolean minportrait;
  private final float msmallestwidthdp;

  private systembarconfig(activity activity, boolean translucentstatusbar, boolean traslucentnavbar) {
    resources res = activity.getresources();
    minportrait = (res.getconfiguration().orientation == configuration.orientation_portrait);
    msmallestwidthdp = getsmallestwidthdp(activity);
    mstatusbarheight = getinternaldimensionsize(res, status_bar_height_res_name);
    mactionbarheight = getactionbarheight(activity);
    mnavigationbarheight = getnavigationbarheight(activity);
    mnavigationbarwidth = getnavigationbarwidth(activity);
    mhasnavigationbar = (mnavigationbarheight > 0);
    mtranslucentstatusbar = translucentstatusbar;
    mtranslucentnavbar = traslucentnavbar;
  }

  @targetapi(14)
  private int getactionbarheight(context context) {
    int result = 0;
    if (build.version.sdk_int >= build.version_codes.ice_cream_sandwich) {
      typedvalue tv = new typedvalue();
      context.gettheme().resolveattribute(android.r.attr.actionbarsize, tv, true);
      result = typedvalue.complextodimensionpixelsize(tv.data, context.getresources().getdisplaymetrics());
    }
    return result;
  }

  @targetapi(14)
  private int getnavigationbarheight(context context) {
    resources res = context.getresources();
    int result = 0;
    if (build.version.sdk_int >= build.version_codes.ice_cream_sandwich) {
      if (hasnavbar(context)) {
        string key;
        if (minportrait) {
          key = nav_bar_height_res_name;
        } else {
          key = nav_bar_height_landscape_res_name;
        }
        return getinternaldimensionsize(res, key);
      }
    }
    return result;
  }

  @targetapi(14)
  private int getnavigationbarwidth(context context) {
    resources res = context.getresources();
    int result = 0;
    if (build.version.sdk_int >= build.version_codes.ice_cream_sandwich) {
      if (hasnavbar(context)) {
        return getinternaldimensionsize(res, nav_bar_width_res_name);
      }
    }
    return result;
  }

  @targetapi(14)
  private boolean hasnavbar(context context) {
    resources res = context.getresources();
    int resourceid = res.getidentifier(show_nav_bar_res_name, "bool", "android");
    if (resourceid != 0) {
      boolean hasnav = res.getboolean(resourceid);
      // check override flag (see static block)
      if ("1".equals(snavbaroverride)) {
        hasnav = false;
      } else if ("0".equals(snavbaroverride)) {
        hasnav = true;
      }
      return hasnav;
    } else { // fallback
      return !viewconfiguration.get(context).haspermanentmenukey();
    }
  }

  private int getinternaldimensionsize(resources res, string key) {
    int result = 0;
    int resourceid = res.getidentifier(key, "dimen", "android");
    if (resourceid > 0) {
      result = res.getdimensionpixelsize(resourceid);
    }
    return result;
  }

  @suppresslint("newapi")
  private float getsmallestwidthdp(activity activity) {
    displaymetrics metrics = new displaymetrics();
    if (build.version.sdk_int >= build.version_codes.jelly_bean) {
      activity.getwindowmanager().getdefaultdisplay().getrealmetrics(metrics);
    } else {
      activity.getwindowmanager().getdefaultdisplay().getmetrics(metrics);
    }
    float widthdp = metrics.widthpixels / metrics.density;
    float heightdp = metrics.heightpixels / metrics.density;
    return math.min(widthdp, heightdp);
  }

  /**
   * should a navigation bar appear at the bottom of the screen in the current
   * device configuration? a navigation bar may appear on the right side of
   * the screen in certain configurations.
   *
   * @return true if navigation should appear at the bottom of the screen, false otherwise.
   */
  public boolean isnavigationatbottom() {
    return (msmallestwidthdp >= 600 || minportrait);
  }

  /**
   * get the height of the system status bar.
   *
   * @return the height of the status bar (in pixels).
   */
  public int getstatusbarheight() {
    return mstatusbarheight;
  }

  /**
   * get the height of the action bar.
   *
   * @return the height of the action bar (in pixels).
   */
  public int getactionbarheight() {
    return mactionbarheight;
  }

  /**
   * does this device have a system navigation bar?
   *
   * @return true if this device uses soft key navigation, false otherwise.
   */
  public boolean hasnavigtionbar() {
    return mhasnavigationbar;
  }

  /**
   * get the height of the system navigation bar.
   *
   * @return the height of the navigation bar (in pixels). if the device does not have
   * soft navigation keys, this will always return 0.
   */
  public int getnavigationbarheight() {
    return mnavigationbarheight;
  }

  /**
   * get the width of the system navigation bar when it is placed vertically on the screen.
   *
   * @return the width of the navigation bar (in pixels). if the device does not have
   * soft navigation keys, this will always return 0.
   */
  public int getnavigationbarwidth() {
    return mnavigationbarwidth;
  }

  /**
   * get the layout inset for any system ui that appears at the top of the screen.
   *
   * @param withactionbar true to include the height of the action bar, false otherwise.
   * @return the layout inset (in pixels).
   */
  public int getpixelinsettop(boolean withactionbar) {
    return (mtranslucentstatusbar ? mstatusbarheight : 0) + (withactionbar ? mactionbarheight : 0);
  }

  /**
   * get the layout inset for any system ui that appears at the bottom of the screen.
   *
   * @return the layout inset (in pixels).
   */
  public int getpixelinsetbottom() {
    if (mtranslucentnavbar && isnavigationatbottom()) {
      return mnavigationbarheight;
    } else {
      return 0;
    }
  }

  /**
   * get the layout inset for any system ui that appears at the right of the screen.
   *
   * @return the layout inset (in pixels).
   */
  public int getpixelinsetright() {
    if (mtranslucentnavbar && !isnavigationatbottom()) {
      return mnavigationbarwidth;
    } else {
      return 0;
    }
  }

}
}

以上就是本文的全部内容,希望大家喜欢。