当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义手机界面状态栏实例代码

Android自定义手机界面状态栏实例代码

2019年07月24日  | 移动技术网IT编程  | 我要评论

人造板网,教师节黑板报设计,二战英豪

前言

我们知道ios上的应用,状态栏的颜色总能与应用标题栏颜色保持一致,用户体验很不错,那安卓是否可以呢?若是在安卓4.4之前,答案是否定的,但在4.4之后,谷歌允许开发者自定义状态栏背景颜色啦,这是个不错的体验!若你手机上安装有最新版的qq,并且你的安卓sdk版本是4.4及以上,你可以看下它的效果:

实现这个效果有两个方法: 1.在xml中设置主题或自定义style;

theme.holo.light.noactionbar.translucentdecor
theme.holo.noactionbar.translucentdecor
<style name="apptheme" parent="appbasetheme"> 
<!-- status bar --> 
<item name="android:windowtranslucentstatus">true</item> 
<!-- navigation bar --> 
<item name="android:windowtranslucentnavigation">true</item> 
</style>

鉴于市面上各种手机的sdk的各种版本,不建议采用这种方法;

2.在代码中控制; 这个情况下可创建一个baseactivity,在oncreate方法中进行处理:

@override 
protected void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 if (build.version.sdk_int >= build.version_codes.kitkat) { 
  settranslucentstatus(true); 
  systembartintmanager tintmanager = new systembartintmanager(this); 
  tintmanager.setstatusbartintenabled(true); 
  tintmanager.setstatusbartintresource(r.color.top_bg_color);//通知栏所需颜色 
 } 
 setcontentview(r.layout.main_activity); 
} 
 @targetapi(19) 
 private void settranslucentstatus(boolean on) { 
 window win = getwindow(); 
 windowmanager.layoutparams winparams = win.getattributes(); 
 final int bits = windowmanager.layoutparams.flag_translucent_status; 
 if (on) { 
  winparams.flags |= bits; 
 } else { 
  winparams.flags &= ~bits; 
 } 
 win.setattributes(winparams); 
 }

需注意的是, tintmanager.setstatusbartintresource(r.color.top_bg_color);这一步的颜色值(即把你的状态栏颜色与你的标题栏颜色保持一致)要写在color.xml中去,如果用color.prasecolor则会报错。

systembartintmanager.java源码代码:
/*
 * copyright (c) 2013 readystate software ltd
 *
 * 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.zhjy.hxf.hzsmallmi.util;
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;
/**
 * class to manage status and navigation bar tint effects when using kitkat 
 * translucent system ui modes.
 *
 */
public class systembartintmanager {
 static {
 // android allows a system property to override the presence of the navigation bar.
 // used by the emulator.
 // see https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/phonewindowmanager.java#l1076
 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 systembartintmanager(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 {
  // todo this is not correct, but we don't really care pre-kitkat
  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;
  }
 }
 }
}

代码复制进你的项目即可,好了,这些工作完成之后我们来看下效果:

貌似已经达到效果了,但仔细观察,好像标题栏被提上去了,就是说app界面全屏了,状态了盖在了app上,恩,这并非我们想要的效果,那如何将界面从状态栏下部开始呢,只需要在activity的布局文件最外层控件加上一个属性: android:fitssystemwindows="true"就可以啦!看下效果:

这样就达到了咱们最开始的样式。

ps:在使用过程中发现了一些问题,使用以上方法对单个activity有效,但是对继承了tabactivity的导航页怎么办呢?假如mainactivity继承了tabactivity,tab1activity、tab2activity、tab3activity是三个子项,那么设置状态栏的代码需写在mainactivity中,而 android:fitssystemwindows="true"需写在三个子activity的xml布局文件中,这样设置后仍然有问题,就是进入应用后首页也就是tab1activity没有问题,而tab2activity、tab3activity却没达到效果,它们的效果相当于未加android:fitssystemwindows="true"时的效果,期初我怀疑是activity不同的原因,因此我把tab1activity和tab3activity调了下位置,结果tab3activity成为首页后正常,而tab1activity又不正常了,百思不得姐,最后实在没办法,就在tab2activity、tab3activity的oncreate方法中加了几句代码:

if (build.version.sdk_int >= build.version_codes.kitkat) { 
 ((linearlayout)findviewbyid(r.id.ll)).setpadding(0, sysutils.getstatusheight(this), 0,0); 
 }

意思是,先求出状态栏高度,然后设置最外层控件的paddingtop值为状态栏高度,结果正好达到效果,至于为什么只有首页activity可以达到效果,而后面的子项无法达到效果,本人也在郁闷中,有知道的朋友可以分享下! 状态栏高度算法:

/** 
  * 状态栏高度算法 
  * @param activity 
  * @return 
  */ 
 public static int getstatusheight(activity activity){ 
  int statusheight = 0; 
  rect localrect = new rect(); 
  activity.getwindow().getdecorview().getwindowvisibledisplayframe(localrect); 
  statusheight = localrect.top; 
  if (0 == statusheight){ 
  class<?> localclass; 
  try { 
   localclass = class.forname("com.android.internal.r$dimen"); 
   object localobject = localclass.newinstance(); 
   int i5 = integer.parseint(localclass.getfield("status_bar_height").get(localobject).tostring()); 
   statusheight = activity.getresources().getdimensionpixelsize(i5); 
  } catch (classnotfoundexception e) { 
   e.printstacktrace(); 
  } catch (illegalaccessexception e) { 
   e.printstacktrace(); 
  } catch (instantiationexception e) { 
   e.printstacktrace(); 
  } catch (numberformatexception e) { 
   e.printstacktrace(); 
  } catch (illegalargumentexception e) { 
   e.printstacktrace(); 
  } catch (securityexception e) { 
   e.printstacktrace(); 
  } catch (nosuchfieldexception e) { 
   e.printstacktrace(); 
  } 
  } 
  return statusheight; 
 }

以上所述是小编给大家介绍的android自定义手机界面状态栏实例代码,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网