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