Android自定义状态栏颜色与APP风格保持一致的实现方法

Android自定义状态栏颜色与APP风格保持一致的实现方法,第1张

概述我们知道iOS上的应用,状态栏颜色总能与应用标题栏颜色保持一致,用户体验很不错,那安卓是否可以呢?若是在安卓4.4之前,答案是否定的,但在4.4之后,谷歌允许开发者自定义状态栏背景颜色啦,这是个不错的体验!若

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

实现此功能有两种方法:

1.在xml中设置主题或自定义style;

theme.Holo.light.NoActionbar.TranslucentDecortheme.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源码:

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. * */ @SuppressWarnings({ "rawtypes","unchecked" }) 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; } } } }

引用自:https://github.com/jgilfelt/SystemBarTint

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

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

AndroID:fitsSystemwindows="true"就可以啦!看下效果:

OK,大功告成!

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); }

意思是,先求出状态栏高度,然后设置最外层控件的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自定义状态栏颜色与APP风格保持一致的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

总结

以上是内存溢出为你收集整理的Android自定义状态栏颜色与APP风格保持一致的实现方法全部内容,希望文章能够帮你解决Android自定义状态栏颜色与APP风格保持一致的实现方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1147994.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存