Android沉浸式状态栏实现
程序员文章站
2024-02-16 23:31:34
苹果上的ui基本上都是这个效果,然而android机上的顶部状态栏总是和app的主题颜色不搭。还好如今的api19以上的版本,我们也能做出这样的效果。
第一步:...
苹果上的ui基本上都是这个效果,然而android机上的顶部状态栏总是和app的主题颜色不搭。还好如今的api19以上的版本,我们也能做出这样的效果。
第一步:
// 需要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; } } } }
以上就是本文的全部内容,希望大家喜欢。