这个特性是andorid4.4支持的,最少要api19才可以使用,也就是说如果Android的机子是低于4.4,沉浸通知栏是没有效果的。下面介绍一下使用的方法,非常得简单。
1 public void initSystemBar() { 2 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 3 setTranslucentStatus(true); 4 SystemBarTintManager tintManager = new SystemBarTintManager(this); 5 tintManager.setStatusBarTintEnabled(true); 6 tintManager.setStatusBarTintResource(R.color.blue); 7 } 8 } 9 10 /**11 * 设置通知栏的状态12 * @param on13 */14 @SuppressLint("InlinedApi") 15 private void setTranslucentStatus(boolean on) { 16 Window win = this.getWindow(); 17 WindowManager.LayoutParams winParams = win.getAttributes(); 18 final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 19 if (on) { 20 winParams.flags |= bits; 21 } else { 22 winParams.flags &= ~bits; 23 } 24 win.setAttributes(winParams); 25 }
1 import java.lang.reflect.Method; 2 3 import android.annotation.SuppressLint; 4 import android.annotation.TargetApi; 5 import android.app.Activity; 6 import android.content.Context; 7 import android.content.res.Configuration; 8 import android.content.res.Resources; 9 import android.content.res.TypedArray; 10 import android.graphics.drawable.Drawable; 11 import android.os.Build; 12 import android.util.DisplayMetrics; 13 import android.util.TypedValue; 14 import android.view.Gravity; 15 import android.view.View; 16 import android.view.ViewConfiguration; 17 import android.view.ViewGroup; 18 import android.view.Window; 19 import android.view.WindowManager; 20 import android.widget.FrameLayout.LayoutParams; 21 22 /** 23 * Class to manage status and navigation bar tint effects when using KitKat 24 * translucent system UI modes. 25 * 26 */ 27 public class SystemBarTintManager { 28 29 static { 30 // Android allows a system property to override the presence of the navigation bar. 31 // Used by the emulator. 32 // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076 33 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 34 try { 35 Class c = Class.forName("android.os.SystemProperties"); 36 Method m = c.getDeclaredMethod("get", String.class); 37 m.setAccessible(true); 38 sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys"); 39 } catch (Throwable e) { 40 sNavBarOverride = null; 41 } 42 } 43 } 44 45 46 /** 47 * The default system bar tint color value. 48 */ 49 public static final int DEFAULT_TINT_COLOR = 0x99000000; 50 51 private static String sNavBarOverride; 52 53 private final SystemBarConfig mConfig; 54 private boolean mStatusBarAvailable; 55 private boolean mNavBarAvailable; 56 private boolean mStatusBarTintEnabled; 57 private boolean mNavBarTintEnabled; 58 private View mStatusBarTintView; 59 private View mNavBarTintView; 60 61 /** 62 * Constructor. Call this in the host activity onCreate method after its 63 * content view has been set. You should always create new instances when 64 * the host activity is recreated. 65 * 66 * @param activity The host activity. 67 */ 68 @TargetApi(19) 69 public SystemBarTintManager(Activity activity) { 70 71 Window win = activity.getWindow(); 72 ViewGroup decorViewGroup = (ViewGroup) win.getDecorView(); 73 74 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 75 // check theme attrs 76 int[] attrs = {android.R.attr.windowTranslucentStatus, 77 android.R.attr.windowTranslucentNavigation}; 78 TypedArray a = activity.obtainStyledAttributes(attrs); 79 try { 80 mStatusBarAvailable = a.getBoolean(0, false); 81 mNavBarAvailable = a.getBoolean(1, false); 82 } finally { 83 a.recycle(); 84 } 85 86 // check window flags 87 WindowManager.LayoutParams winParams = win.getAttributes(); 88 int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 89 if ((winParams.flags & bits) != 0) { 90 mStatusBarAvailable = true; 91 } 92 bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; 93 if ((winParams.flags & bits) != 0) { 94 mNavBarAvailable = true; 95 } 96 } 97 98 mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable); 99 // device might not have virtual navigation keys100 if (!mConfig.hasNavigtionBar()) {101 mNavBarAvailable = false;102 }103 104 if (mStatusBarAvailable) {105 setupStatusBarView(activity, decorViewGroup);106 }107 if (mNavBarAvailable) {108 setupNavBarView(activity, decorViewGroup);109 }110 111 }112 113 /**114 * Enable tinting of the system status bar.115 *116 * If the platform is running Jelly Bean or earlier, or translucent system117 * UI modes have not been enabled in either the theme or via window flags,118 * then this method does nothing.119 *120 * @param enabled True to enable tinting, false to disable it (default).121 */122 public void setStatusBarTintEnabled(boolean enabled) {123 mStatusBarTintEnabled = enabled;124 if (mStatusBarAvailable) {125 mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);126 }127 }128 129 /**130 * Enable tinting of the system navigation bar.131 *132 * If the platform does not have soft navigation keys, is running Jelly Bean133 * or earlier, or translucent system UI modes have not been enabled in either134 * the theme or via window flags, then this method does nothing.135 *136 * @param enabled True to enable tinting, false to disable it (default).137 */138 public void setNavigationBarTintEnabled(boolean enabled) {139 mNavBarTintEnabled = enabled;140 if (mNavBarAvailable) {141 mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);142 }143 }144 145 /**146 * Apply the specified color tint to all system UI bars.147 *148 * @param color The color of the background tint.149 */150 public void setTintColor(int color) {151 setStatusBarTintColor(color);152 setNavigationBarTintColor(color);153 }154 155 /**156 * Apply the specified drawable or color resource to all system UI bars.157 *158 * @param res The identifier of the resource.159 */160 public void setTintResource(int res) {161 setStatusBarTintResource(res);162 setNavigationBarTintResource(res);163 }164 165 /**166 * Apply the specified drawable to all system UI bars.167 *168 * @param drawable The drawable to use as the background, or null to remove it.169 */170 public void setTintDrawable(Drawable drawable) {171 setStatusBarTintDrawable(drawable);172 setNavigationBarTintDrawable(drawable);173 }174 175 /**176 * Apply the specified alpha to all system UI bars.177 *178 * @param alpha The alpha to use179 */180 public void setTintAlpha(float alpha) {181 setStatusBarAlpha(alpha);182 setNavigationBarAlpha(alpha);183 }184 185 /**186 * Apply the specified color tint to the system status bar.187 *188 * @param color The color of the background tint.189 */190 public void setStatusBarTintColor(int color) {191 if (mStatusBarAvailable) {192 mStatusBarTintView.setBackgroundColor(color);193 }194 }195 196 /**197 * Apply the specified drawable or color resource to the system status bar.198 *199 * @param res The identifier of the resource.200 */201 public void setStatusBarTintResource(int res) {202 if (mStatusBarAvailable) {203 mStatusBarTintView.setBackgroundResource(res);204 }205 }206 207 /**208 * Apply the specified drawable to the system status bar.209 *210 * @param drawable The drawable to use as the background, or null to remove it.211 */212 @SuppressWarnings("deprecation")213 public void setStatusBarTintDrawable(Drawable drawable) {214 if (mStatusBarAvailable) {215 mStatusBarTintView.setBackgroundDrawable(drawable);216 }217 }218 219 /**220 * Apply the specified alpha to the system status bar.221 *222 * @param alpha The alpha to use223 */224 @TargetApi(11)225 public void setStatusBarAlpha(float alpha) {226 if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {227 mStatusBarTintView.setAlpha(alpha);228 }229 }230 231 /**232 * Apply the specified color tint to the system navigation bar.233 *234 * @param color The color of the background tint.235 */236 public void setNavigationBarTintColor(int color) {237 if (mNavBarAvailable) {238 mNavBarTintView.setBackgroundColor(color);239 }240 }241 242 /**243 * Apply the specified drawable or color resource to the system navigation bar.244 *245 * @param res The identifier of the resource.246 */247 public void setNavigationBarTintResource(int res) {248 if (mNavBarAvailable) {249 mNavBarTintView.setBackgroundResource(res);250 }251 }252 253 /**254 * Apply the specified drawable to the system navigation bar.255 *256 * @param drawable The drawable to use as the background, or null to remove it.257 */258 @SuppressWarnings("deprecation")259 public void setNavigationBarTintDrawable(Drawable drawable) {260 if (mNavBarAvailable) {261 mNavBarTintView.setBackgroundDrawable(drawable);262 }263 }264 265 /**266 * Apply the specified alpha to the system navigation bar.267 *268 * @param alpha The alpha to use269 */270 @TargetApi(11)271 public void setNavigationBarAlpha(float alpha) {272 if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {273 mNavBarTintView.setAlpha(alpha);274 }275 }276 277 /**278 * Get the system bar configuration.279 *280 * @return The system bar configuration for the current device configuration.281 */282 public SystemBarConfig getConfig() {283 return mConfig;284 }285 286 /**287 * Is tinting enabled for the system status bar?288 *289 * @return True if enabled, False otherwise.290 */291 public boolean isStatusBarTintEnabled() {292 return mStatusBarTintEnabled;293 }294 295 /**296 * Is tinting enabled for the system navigation bar?297 *298 * @return True if enabled, False otherwise.299 */300 public boolean isNavBarTintEnabled() {301 return mNavBarTintEnabled;302 }303 304 private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {305 mStatusBarTintView = new View(context);306 LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());307 params.gravity = Gravity.TOP;308 if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {309 params.rightMargin = mConfig.getNavigationBarWidth();310 }311 mStatusBarTintView.setLayoutParams(params);312 mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);313 mStatusBarTintView.setVisibility(View.GONE);314 decorViewGroup.addView(mStatusBarTintView);315 }316 317 private void setupNavBarView(Context context, ViewGroup decorViewGroup) {318 mNavBarTintView = new View(context);319 LayoutParams params;320 if (mConfig.isNavigationAtBottom()) {321 params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());322 params.gravity = Gravity.BOTTOM;323 } else {324 params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT);325 params.gravity = Gravity.RIGHT;326 }327 mNavBarTintView.setLayoutParams(params);328 mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);329 mNavBarTintView.setVisibility(View.GONE);330 decorViewGroup.addView(mNavBarTintView);331 }332 333 /**334 * Class which describes system bar sizing and other characteristics for the current335 * device configuration.336 *337 */338 public static class SystemBarConfig {339 340 private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";341 private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";342 private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";343 private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";344 private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";345 346 private final boolean mTranslucentStatusBar;347 private final boolean mTranslucentNavBar;348 private final int mStatusBarHeight;349 private final int mActionBarHeight;350 private final boolean mHasNavigationBar;351 private final int mNavigationBarHeight;352 private final int mNavigationBarWidth;353 private final boolean mInPortrait;354 private final float mSmallestWidthDp;355 356 private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {357 Resources res = activity.getResources();358 mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);359 mSmallestWidthDp = getSmallestWidthDp(activity);360 mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);361 mActionBarHeight = getActionBarHeight(activity);362 mNavigationBarHeight = getNavigationBarHeight(activity);363 mNavigationBarWidth = getNavigationBarWidth(activity);364 mHasNavigationBar = (mNavigationBarHeight > 0);365 mTranslucentStatusBar = translucentStatusBar;366 mTranslucentNavBar = traslucentNavBar;367 }368 369 @TargetApi(14)370 private int getActionBarHeight(Context context) {371 int result = 0;372 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {373 TypedValue tv = new TypedValue();374 context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);375 result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());376 }377 return result;378 }379 380 @TargetApi(14)381 private int getNavigationBarHeight(Context context) {382 Resources res = context.getResources();383 int result = 0;384 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {385 if (hasNavBar(context)) {386 String key;387 if (mInPortrait) {388 key = NAV_BAR_HEIGHT_RES_NAME;389 } else {390 key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;391 }392 return getInternalDimensionSize(res, key);393 }394 }395 return result;396 }397 398 @TargetApi(14)399 private int getNavigationBarWidth(Context context) {400 Resources res = context.getResources();401 int result = 0;402 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {403 if (hasNavBar(context)) {404 return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);405 }406 }407 return result;408 }409 410 @TargetApi(14)411 private boolean hasNavBar(Context context) {412 Resources res = context.getResources();413 int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");414 if (resourceId != 0) {415 boolean hasNav = res.getBoolean(resourceId);416 // check override flag (see static block)417 if ("1".equals(sNavBarOverride)) {418 hasNav = false;419 } else if ("0".equals(sNavBarOverride)) {420 hasNav = true;421 }422 return hasNav;423 } else { // fallback424 return !ViewConfiguration.get(context).hasPermanentMenuKey();425 }426 }427 428 private int getInternalDimensionSize(Resources res, String key) {429 int result = 0;430 int resourceId = res.getIdentifier(key, "dimen", "android");431 if (resourceId > 0) {432 result = res.getDimensionPixelSize(resourceId);433 }434 return result;435 }436 437 @SuppressLint("NewApi")438 private float getSmallestWidthDp(Activity activity) {439 DisplayMetrics metrics = new DisplayMetrics();440 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {441 activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);442 } else {443 // TODO this is not correct, but we don't really care pre-kitkat444 activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);445 }446 float widthDp = metrics.widthPixels / metrics.density;447 float heightDp = metrics.heightPixels / metrics.density;448 return Math.min(widthDp, heightDp);449 }450 451 /**452 * Should a navigation bar appear at the bottom of the screen in the current453 * device configuration? A navigation bar may appear on the right side of454 * the screen in certain configurations.455 *456 * @return True if navigation should appear at the bottom of the screen, False otherwise.457 */458 public boolean isNavigationAtBottom() {459 return (mSmallestWidthDp >= 600 || mInPortrait);460 }461 462 /**463 * Get the height of the system status bar.464 *465 * @return The height of the status bar (in pixels).466 */467 public int getStatusBarHeight() {468 return mStatusBarHeight;469 }470 471 /**472 * Get the height of the action bar.473 *474 * @return The height of the action bar (in pixels).475 */476 public int getActionBarHeight() {477 return mActionBarHeight;478 }479 480 /**481 * Does this device have a system navigation bar?482 *483 * @return True if this device uses soft key navigation, False otherwise.484 */485 public boolean hasNavigtionBar() {486 return mHasNavigationBar;487 }488 489 /**490 * Get the height of the system navigation bar.491 *492 * @return The height of the navigation bar (in pixels). If the device does not have493 * soft navigation keys, this will always return 0.494 */495 public int getNavigationBarHeight() {496 return mNavigationBarHeight;497 }498 499 /**500 * Get the width of the system navigation bar when it is placed vertically on the screen.501 *502 * @return The width of the navigation bar (in pixels). If the device does not have503 * soft navigation keys, this will always return 0.504 */505 public int getNavigationBarWidth() {506 return mNavigationBarWidth;507 }508 509 /**510 * Get the layout inset for any system UI that appears at the top of the screen.511 *512 * @param withActionBar True to include the height of the action bar, False otherwise.513 * @return The layout inset (in pixels).514 */515 public int getPixelInsetTop(boolean withActionBar) {516 return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);517 }518 519 /**520 * Get the layout inset for any system UI that appears at the bottom of the screen.521 *522 * @return The layout inset (in pixels).523 */524 public int getPixelInsetBottom() {525 if (mTranslucentNavBar && isNavigationAtBottom()) {526 return mNavigationBarHeight;527 } else {528 return 0;529 }530 }531 532 /**533 * Get the layout inset for any system UI that appears at the right of the screen.534 *535 * @return The layout inset (in pixels).536 */537 public int getPixelInsetRight() {538 if (mTranslucentNavBar && !isNavigationAtBottom()) {539 return mNavigationBarWidth;540 } else {541 return 0;542 }543 }544 545 }
在最后在布局文件中添加:android:fitsSystemWindows="true"
即可实现。