透明通知栏"/>
Android开发实现透明通知栏
这个特性是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 on 13 */ 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 .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 keys 100 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 system 117 * 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 Bean 133 * or earlier, or translucent system UI modes have not been enabled in either 134 * 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 use 179 */ 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 use 223 */ 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 use 269 */ 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 current 335 * 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 = TypedValueplexToDimensionPixelSize(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 { // fallback 424 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-kitkat 444 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 current 453 * device configuration? A navigation bar may appear on the right side of 454 * 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 have 493 * 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 have 503 * 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"
即可实现。
转载于:.html
更多推荐
Android开发实现透明通知栏
发布评论