WindowInsets.java revision 0ffd49cbe0ab4c13fd5528abacade898a8cff481
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18package android.view; 19 20import android.graphics.Rect; 21 22/** 23 * Describes a set of insets for window content. 24 * 25 * <p>WindowInsets are immutable and may be expanded to include more inset types in the future. 26 * To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance 27 * with the adjusted properties.</p> 28 * 29 * @see View.OnApplyWindowInsetsListener 30 * @see View#onApplyWindowInsets(WindowInsets) 31 */ 32public final class WindowInsets { 33 34 private Rect mSystemWindowInsets; 35 private Rect mWindowDecorInsets; 36 private Rect mStableInsets; 37 private Rect mTempRect; 38 private boolean mIsRound; 39 40 /** 41 * In multi-window we force show the navigation bar. Because we don't want that the surface size 42 * changes in this mode, we instead have a flag whether the navigation bar size should always 43 * be consumed, so the app is treated like there is no virtual navigation bar at all. 44 */ 45 private boolean mAlwaysConsumeNavBar; 46 47 private boolean mSystemWindowInsetsConsumed = false; 48 private boolean mWindowDecorInsetsConsumed = false; 49 private boolean mStableInsetsConsumed = false; 50 51 private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0); 52 53 /** 54 * Since new insets may be added in the future that existing apps couldn't 55 * know about, this fully empty constant shouldn't be made available to apps 56 * since it would allow them to inadvertently consume unknown insets by returning it. 57 * @hide 58 */ 59 public static final WindowInsets CONSUMED; 60 61 static { 62 CONSUMED = new WindowInsets(null, null, null, false, false); 63 } 64 65 /** @hide */ 66 public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets, 67 boolean isRound, boolean alwaysConsumeNavBar) { 68 mSystemWindowInsetsConsumed = systemWindowInsets == null; 69 mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets; 70 71 mWindowDecorInsetsConsumed = windowDecorInsets == null; 72 mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : windowDecorInsets; 73 74 mStableInsetsConsumed = stableInsets == null; 75 mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : stableInsets; 76 77 mIsRound = isRound; 78 mAlwaysConsumeNavBar = alwaysConsumeNavBar; 79 } 80 81 /** 82 * Construct a new WindowInsets, copying all values from a source WindowInsets. 83 * 84 * @param src Source to copy insets from 85 */ 86 public WindowInsets(WindowInsets src) { 87 mSystemWindowInsets = src.mSystemWindowInsets; 88 mWindowDecorInsets = src.mWindowDecorInsets; 89 mStableInsets = src.mStableInsets; 90 mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed; 91 mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed; 92 mStableInsetsConsumed = src.mStableInsetsConsumed; 93 mIsRound = src.mIsRound; 94 } 95 96 /** @hide */ 97 public WindowInsets(Rect systemWindowInsets) { 98 this(systemWindowInsets, null, null, false, false); 99 } 100 101 /** 102 * Used to provide a safe copy of the system window insets to pass through 103 * to the existing fitSystemWindows method and other similar internals. 104 * @hide 105 */ 106 public Rect getSystemWindowInsets() { 107 if (mTempRect == null) { 108 mTempRect = new Rect(); 109 } 110 if (mSystemWindowInsets != null) { 111 mTempRect.set(mSystemWindowInsets); 112 } else { 113 // If there were no system window insets, this is just empty. 114 mTempRect.setEmpty(); 115 } 116 return mTempRect; 117 } 118 119 /** 120 * Returns the left system window inset in pixels. 121 * 122 * <p>The system window inset represents the area of a full-screen window that is 123 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 124 * </p> 125 * 126 * @return The left system window inset 127 */ 128 public int getSystemWindowInsetLeft() { 129 return mSystemWindowInsets.left; 130 } 131 132 /** 133 * Returns the top system window inset in pixels. 134 * 135 * <p>The system window inset represents the area of a full-screen window that is 136 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 137 * </p> 138 * 139 * @return The top system window inset 140 */ 141 public int getSystemWindowInsetTop() { 142 return mSystemWindowInsets.top; 143 } 144 145 /** 146 * Returns the right system window inset in pixels. 147 * 148 * <p>The system window inset represents the area of a full-screen window that is 149 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 150 * </p> 151 * 152 * @return The right system window inset 153 */ 154 public int getSystemWindowInsetRight() { 155 return mSystemWindowInsets.right; 156 } 157 158 /** 159 * Returns the bottom system window inset in pixels. 160 * 161 * <p>The system window inset represents the area of a full-screen window that is 162 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 163 * </p> 164 * 165 * @return The bottom system window inset 166 */ 167 public int getSystemWindowInsetBottom() { 168 return mSystemWindowInsets.bottom; 169 } 170 171 /** 172 * Returns the left window decor inset in pixels. 173 * 174 * <p>The window decor inset represents the area of the window content area that is 175 * partially or fully obscured by decorations within the window provided by the framework. 176 * This can include action bars, title bars, toolbars, etc.</p> 177 * 178 * @return The left window decor inset 179 * @hide pending API 180 */ 181 public int getWindowDecorInsetLeft() { 182 return mWindowDecorInsets.left; 183 } 184 185 /** 186 * Returns the top window decor inset in pixels. 187 * 188 * <p>The window decor inset represents the area of the window content area that is 189 * partially or fully obscured by decorations within the window provided by the framework. 190 * This can include action bars, title bars, toolbars, etc.</p> 191 * 192 * @return The top window decor inset 193 * @hide pending API 194 */ 195 public int getWindowDecorInsetTop() { 196 return mWindowDecorInsets.top; 197 } 198 199 /** 200 * Returns the right window decor inset in pixels. 201 * 202 * <p>The window decor inset represents the area of the window content area that is 203 * partially or fully obscured by decorations within the window provided by the framework. 204 * This can include action bars, title bars, toolbars, etc.</p> 205 * 206 * @return The right window decor inset 207 * @hide pending API 208 */ 209 public int getWindowDecorInsetRight() { 210 return mWindowDecorInsets.right; 211 } 212 213 /** 214 * Returns the bottom window decor inset in pixels. 215 * 216 * <p>The window decor inset represents the area of the window content area that is 217 * partially or fully obscured by decorations within the window provided by the framework. 218 * This can include action bars, title bars, toolbars, etc.</p> 219 * 220 * @return The bottom window decor inset 221 * @hide pending API 222 */ 223 public int getWindowDecorInsetBottom() { 224 return mWindowDecorInsets.bottom; 225 } 226 227 /** 228 * Returns true if this WindowInsets has nonzero system window insets. 229 * 230 * <p>The system window inset represents the area of a full-screen window that is 231 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 232 * </p> 233 * 234 * @return true if any of the system window inset values are nonzero 235 */ 236 public boolean hasSystemWindowInsets() { 237 return mSystemWindowInsets.left != 0 || mSystemWindowInsets.top != 0 || 238 mSystemWindowInsets.right != 0 || mSystemWindowInsets.bottom != 0; 239 } 240 241 /** 242 * Returns true if this WindowInsets has nonzero window decor insets. 243 * 244 * <p>The window decor inset represents the area of the window content area that is 245 * partially or fully obscured by decorations within the window provided by the framework. 246 * This can include action bars, title bars, toolbars, etc.</p> 247 * 248 * @return true if any of the window decor inset values are nonzero 249 * @hide pending API 250 */ 251 public boolean hasWindowDecorInsets() { 252 return mWindowDecorInsets.left != 0 || mWindowDecorInsets.top != 0 || 253 mWindowDecorInsets.right != 0 || mWindowDecorInsets.bottom != 0; 254 } 255 256 /** 257 * Returns true if this WindowInsets has any nonzero insets. 258 * 259 * @return true if any inset values are nonzero 260 */ 261 public boolean hasInsets() { 262 return hasSystemWindowInsets() || hasWindowDecorInsets() || hasStableInsets(); 263 } 264 265 /** 266 * Check if these insets have been fully consumed. 267 * 268 * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods 269 * have been called such that all insets have been set to zero. This affects propagation of 270 * insets through the view hierarchy; insets that have not been fully consumed will continue 271 * to propagate down to child views.</p> 272 * 273 * <p>The result of this method is equivalent to the return value of 274 * {@link View#fitSystemWindows(android.graphics.Rect)}.</p> 275 * 276 * @return true if the insets have been fully consumed. 277 */ 278 public boolean isConsumed() { 279 return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed; 280 } 281 282 /** 283 * Returns true if the associated window has a round shape. 284 * 285 * <p>A round window's left, top, right and bottom edges reach all the way to the 286 * associated edges of the window but the corners may not be visible. Views responding 287 * to round insets should take care to not lay out critical elements within the corners 288 * where they may not be accessible.</p> 289 * 290 * @return True if the window is round 291 */ 292 public boolean isRound() { 293 return mIsRound; 294 } 295 296 /** 297 * Returns a copy of this WindowInsets with the system window insets fully consumed. 298 * 299 * @return A modified copy of this WindowInsets 300 */ 301 public WindowInsets consumeSystemWindowInsets() { 302 final WindowInsets result = new WindowInsets(this); 303 result.mSystemWindowInsets = EMPTY_RECT; 304 result.mSystemWindowInsetsConsumed = true; 305 return result; 306 } 307 308 /** 309 * Returns a copy of this WindowInsets with selected system window insets fully consumed. 310 * 311 * @param left true to consume the left system window inset 312 * @param top true to consume the top system window inset 313 * @param right true to consume the right system window inset 314 * @param bottom true to consume the bottom system window inset 315 * @return A modified copy of this WindowInsets 316 * @hide pending API 317 */ 318 public WindowInsets consumeSystemWindowInsets(boolean left, boolean top, 319 boolean right, boolean bottom) { 320 if (left || top || right || bottom) { 321 final WindowInsets result = new WindowInsets(this); 322 result.mSystemWindowInsets = new Rect( 323 left ? 0 : mSystemWindowInsets.left, 324 top ? 0 : mSystemWindowInsets.top, 325 right ? 0 : mSystemWindowInsets.right, 326 bottom ? 0 : mSystemWindowInsets.bottom); 327 return result; 328 } 329 return this; 330 } 331 332 /** 333 * Returns a copy of this WindowInsets with selected system window insets replaced 334 * with new values. 335 * 336 * @param left New left inset in pixels 337 * @param top New top inset in pixels 338 * @param right New right inset in pixels 339 * @param bottom New bottom inset in pixels 340 * @return A modified copy of this WindowInsets 341 */ 342 public WindowInsets replaceSystemWindowInsets(int left, int top, 343 int right, int bottom) { 344 final WindowInsets result = new WindowInsets(this); 345 result.mSystemWindowInsets = new Rect(left, top, right, bottom); 346 return result; 347 } 348 349 /** 350 * Returns a copy of this WindowInsets with selected system window insets replaced 351 * with new values. 352 * 353 * @param systemWindowInsets New system window insets. Each field is the inset in pixels 354 * for that edge 355 * @return A modified copy of this WindowInsets 356 */ 357 public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) { 358 final WindowInsets result = new WindowInsets(this); 359 result.mSystemWindowInsets = new Rect(systemWindowInsets); 360 return result; 361 } 362 363 /** 364 * @hide 365 */ 366 public WindowInsets consumeWindowDecorInsets() { 367 final WindowInsets result = new WindowInsets(this); 368 result.mWindowDecorInsets.set(0, 0, 0, 0); 369 result.mWindowDecorInsetsConsumed = true; 370 return result; 371 } 372 373 /** 374 * @hide 375 */ 376 public WindowInsets consumeWindowDecorInsets(boolean left, boolean top, 377 boolean right, boolean bottom) { 378 if (left || top || right || bottom) { 379 final WindowInsets result = new WindowInsets(this); 380 result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left, 381 top ? 0 : mWindowDecorInsets.top, 382 right ? 0 : mWindowDecorInsets.right, 383 bottom ? 0 : mWindowDecorInsets.bottom); 384 return result; 385 } 386 return this; 387 } 388 389 /** 390 * @hide 391 */ 392 public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) { 393 final WindowInsets result = new WindowInsets(this); 394 result.mWindowDecorInsets = new Rect(left, top, right, bottom); 395 return result; 396 } 397 398 /** 399 * Returns the top stable inset in pixels. 400 * 401 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 402 * partially or fully obscured by the system UI elements. This value does not change 403 * based on the visibility state of those elements; for example, if the status bar is 404 * normally shown, but temporarily hidden, the stable inset will still provide the inset 405 * associated with the status bar being shown.</p> 406 * 407 * @return The top stable inset 408 */ 409 public int getStableInsetTop() { 410 return mStableInsets.top; 411 } 412 413 /** 414 * Returns the left stable inset in pixels. 415 * 416 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 417 * partially or fully obscured by the system UI elements. This value does not change 418 * based on the visibility state of those elements; for example, if the status bar is 419 * normally shown, but temporarily hidden, the stable inset will still provide the inset 420 * associated with the status bar being shown.</p> 421 * 422 * @return The left stable inset 423 */ 424 public int getStableInsetLeft() { 425 return mStableInsets.left; 426 } 427 428 /** 429 * Returns the right stable inset in pixels. 430 * 431 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 432 * partially or fully obscured by the system UI elements. This value does not change 433 * based on the visibility state of those elements; for example, if the status bar is 434 * normally shown, but temporarily hidden, the stable inset will still provide the inset 435 * associated with the status bar being shown.</p> 436 * 437 * @return The right stable inset 438 */ 439 public int getStableInsetRight() { 440 return mStableInsets.right; 441 } 442 443 /** 444 * Returns the bottom stable inset in pixels. 445 * 446 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 447 * partially or fully obscured by the system UI elements. This value does not change 448 * based on the visibility state of those elements; for example, if the status bar is 449 * normally shown, but temporarily hidden, the stable inset will still provide the inset 450 * associated with the status bar being shown.</p> 451 * 452 * @return The bottom stable inset 453 */ 454 public int getStableInsetBottom() { 455 return mStableInsets.bottom; 456 } 457 458 /** 459 * Returns true if this WindowInsets has nonzero stable insets. 460 * 461 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 462 * partially or fully obscured by the system UI elements. This value does not change 463 * based on the visibility state of those elements; for example, if the status bar is 464 * normally shown, but temporarily hidden, the stable inset will still provide the inset 465 * associated with the status bar being shown.</p> 466 * 467 * @return true if any of the stable inset values are nonzero 468 */ 469 public boolean hasStableInsets() { 470 return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0 471 || mStableInsets.bottom != 0; 472 } 473 474 /** 475 * Returns a copy of this WindowInsets with the stable insets fully consumed. 476 * 477 * @return A modified copy of this WindowInsets 478 */ 479 public WindowInsets consumeStableInsets() { 480 final WindowInsets result = new WindowInsets(this); 481 result.mStableInsets = EMPTY_RECT; 482 result.mStableInsetsConsumed = true; 483 return result; 484 } 485 486 /** 487 * @hide 488 */ 489 public boolean shouldAlwaysConsumeNavBar() { 490 return mAlwaysConsumeNavBar; 491 } 492 493 @Override 494 public String toString() { 495 return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets 496 + " windowDecorInsets=" + mWindowDecorInsets 497 + " stableInsets=" + mStableInsets + 498 (isRound() ? " round}" : "}"); 499 } 500} 501