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 18 package android.view; 19 20 import static android.view.WindowInsets.Type.FIRST; 21 import static android.view.WindowInsets.Type.IME; 22 import static android.view.WindowInsets.Type.LAST; 23 import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES; 24 import static android.view.WindowInsets.Type.SIDE_BARS; 25 import static android.view.WindowInsets.Type.SIZE; 26 import static android.view.WindowInsets.Type.SYSTEM_GESTURES; 27 import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT; 28 import static android.view.WindowInsets.Type.TOP_BAR; 29 import static android.view.WindowInsets.Type.all; 30 import static android.view.WindowInsets.Type.compatSystemInsets; 31 import static android.view.WindowInsets.Type.indexOf; 32 33 import android.annotation.IntDef; 34 import android.annotation.IntRange; 35 import android.annotation.NonNull; 36 import android.annotation.Nullable; 37 import android.annotation.UnsupportedAppUsage; 38 import android.graphics.Insets; 39 import android.graphics.Rect; 40 import android.util.SparseArray; 41 import android.view.WindowInsets.Type.InsetType; 42 import android.view.inputmethod.EditorInfo; 43 import android.view.inputmethod.InputMethod; 44 45 import com.android.internal.util.Preconditions; 46 47 import java.lang.annotation.Retention; 48 import java.lang.annotation.RetentionPolicy; 49 import java.util.Arrays; 50 import java.util.Objects; 51 52 /** 53 * Describes a set of insets for window content. 54 * 55 * <p>WindowInsets are immutable and may be expanded to include more inset types in the future. 56 * To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance 57 * with the adjusted properties.</p> 58 * 59 * <p>Note: Before {@link android.os.Build.VERSION_CODES#P P}, WindowInsets instances were only 60 * immutable during a single layout pass (i.e. would return the same values between 61 * {@link View#onApplyWindowInsets} and {@link View#onLayout}, but could return other values 62 * otherwise). Starting with {@link android.os.Build.VERSION_CODES#P P}, WindowInsets are 63 * always immutable and implement equality. 64 * 65 * @see View.OnApplyWindowInsetsListener 66 * @see View#onApplyWindowInsets(WindowInsets) 67 */ 68 public final class WindowInsets { 69 70 private final Insets[] mTypeInsetsMap; 71 private final Insets[] mTypeMaxInsetsMap; 72 private final boolean[] mTypeVisibilityMap; 73 74 @Nullable private Rect mTempRect; 75 private final boolean mIsRound; 76 @Nullable private final DisplayCutout mDisplayCutout; 77 78 /** 79 * In multi-window we force show the navigation bar. Because we don't want that the surface size 80 * changes in this mode, we instead have a flag whether the navigation bar size should always 81 * be consumed, so the app is treated like there is no virtual navigation bar at all. 82 */ 83 private final boolean mAlwaysConsumeSystemBars; 84 85 private final boolean mSystemWindowInsetsConsumed; 86 private final boolean mStableInsetsConsumed; 87 private final boolean mDisplayCutoutConsumed; 88 89 /** 90 * Since new insets may be added in the future that existing apps couldn't 91 * know about, this fully empty constant shouldn't be made available to apps 92 * since it would allow them to inadvertently consume unknown insets by returning it. 93 * @hide 94 */ 95 @UnsupportedAppUsage 96 public static final WindowInsets CONSUMED; 97 98 static { 99 CONSUMED = new WindowInsets((Rect) null, null, false, false, null); 100 } 101 102 /** 103 * Construct a new WindowInsets from individual insets. 104 * 105 * A {@code null} inset indicates that the respective inset is consumed. 106 * 107 * @hide 108 * @deprecated Use {@link WindowInsets(SparseArray, SparseArray, boolean, boolean, DisplayCutout)} 109 */ WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect, boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout)110 public WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect, 111 boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) { 112 this(createCompatTypeMap(systemWindowInsetsRect), createCompatTypeMap(stableInsetsRect), 113 createCompatVisibilityMap(createCompatTypeMap(systemWindowInsetsRect)), 114 isRound, alwaysConsumeSystemBars, displayCutout); 115 } 116 117 /** 118 * Construct a new WindowInsets from individual insets. 119 * 120 * {@code typeInsetsMap} and {@code typeMaxInsetsMap} are a map of indexOf(type) -> insets that 121 * contain the information what kind of system bars causes how much insets. The insets in this 122 * map are non-additive; i.e. they have the same origin. In other words: If two system bars 123 * overlap on one side, the insets of the larger bar will also include the insets of the smaller 124 * bar. 125 * 126 * {@code null} type inset map indicates that the respective inset is fully consumed. 127 * @hide 128 */ WindowInsets(@ullable Insets[] typeInsetsMap, @Nullable Insets[] typeMaxInsetsMap, boolean[] typeVisibilityMap, boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout)129 public WindowInsets(@Nullable Insets[] typeInsetsMap, 130 @Nullable Insets[] typeMaxInsetsMap, 131 boolean[] typeVisibilityMap, 132 boolean isRound, 133 boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) { 134 mSystemWindowInsetsConsumed = typeInsetsMap == null; 135 mTypeInsetsMap = mSystemWindowInsetsConsumed 136 ? new Insets[SIZE] 137 : typeInsetsMap.clone(); 138 139 mStableInsetsConsumed = typeMaxInsetsMap == null; 140 mTypeMaxInsetsMap = mStableInsetsConsumed 141 ? new Insets[SIZE] 142 : typeMaxInsetsMap.clone(); 143 144 mTypeVisibilityMap = typeVisibilityMap; 145 mIsRound = isRound; 146 mAlwaysConsumeSystemBars = alwaysConsumeSystemBars; 147 148 mDisplayCutoutConsumed = displayCutout == null; 149 mDisplayCutout = (mDisplayCutoutConsumed || displayCutout.isEmpty()) 150 ? null : displayCutout; 151 } 152 153 /** 154 * Construct a new WindowInsets, copying all values from a source WindowInsets. 155 * 156 * @param src Source to copy insets from 157 */ WindowInsets(WindowInsets src)158 public WindowInsets(WindowInsets src) { 159 this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap, 160 src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap, 161 src.mTypeVisibilityMap, src.mIsRound, 162 src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src)); 163 } 164 displayCutoutCopyConstructorArgument(WindowInsets w)165 private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) { 166 if (w.mDisplayCutoutConsumed) { 167 return null; 168 } else if (w.mDisplayCutout == null) { 169 return DisplayCutout.NO_CUTOUT; 170 } else { 171 return w.mDisplayCutout; 172 } 173 } 174 175 /** 176 * @return The insets that include system bars indicated by {@code typeMask}, taken from 177 * {@code typeInsetMap}. 178 */ getInsets(Insets[] typeInsetsMap, @InsetType int typeMask)179 private static Insets getInsets(Insets[] typeInsetsMap, @InsetType int typeMask) { 180 Insets result = null; 181 for (int i = FIRST; i <= LAST; i = i << 1) { 182 if ((typeMask & i) == 0) { 183 continue; 184 } 185 Insets insets = typeInsetsMap[indexOf(i)]; 186 if (insets == null) { 187 continue; 188 } 189 if (result == null) { 190 result = insets; 191 } else { 192 result = Insets.max(result, insets); 193 } 194 } 195 return result == null ? Insets.NONE : result; 196 } 197 198 /** 199 * Sets all entries in {@code typeInsetsMap} that belong to {@code typeMask} to {@code insets}, 200 */ setInsets(Insets[] typeInsetsMap, @InsetType int typeMask, Insets insets)201 private static void setInsets(Insets[] typeInsetsMap, @InsetType int typeMask, Insets insets) { 202 for (int i = FIRST; i <= LAST; i = i << 1) { 203 if ((typeMask & i) == 0) { 204 continue; 205 } 206 typeInsetsMap[indexOf(i)] = insets; 207 } 208 } 209 210 /** @hide */ 211 @UnsupportedAppUsage WindowInsets(Rect systemWindowInsets)212 public WindowInsets(Rect systemWindowInsets) { 213 this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, null); 214 } 215 216 /** 217 * Creates a indexOf(type) -> inset map for which the {@code insets} is just mapped to 218 * {@link InsetType#topBar()} and {@link InsetType#sideBars()}, depending on the location of the 219 * inset. 220 */ createCompatTypeMap(@ullable Rect insets)221 private static Insets[] createCompatTypeMap(@Nullable Rect insets) { 222 if (insets == null) { 223 return null; 224 } 225 Insets[] typeInsetMap = new Insets[SIZE]; 226 assignCompatInsets(typeInsetMap, insets); 227 return typeInsetMap; 228 } 229 230 /** 231 * @hide 232 */ assignCompatInsets(Insets[] typeInsetMap, Rect insets)233 static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) { 234 typeInsetMap[indexOf(TOP_BAR)] = Insets.of(0, insets.top, 0, 0); 235 typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom); 236 } 237 createCompatVisibilityMap(@ullable Insets[] typeInsetMap)238 private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetMap) { 239 boolean[] typeVisibilityMap = new boolean[SIZE]; 240 if (typeInsetMap == null) { 241 return typeVisibilityMap; 242 } 243 for (int i = FIRST; i <= LAST; i = i << 1) { 244 int index = indexOf(i); 245 if (!Insets.NONE.equals(typeInsetMap[index])) { 246 typeVisibilityMap[index] = true; 247 } 248 } 249 return typeVisibilityMap; 250 } 251 252 /** 253 * Used to provide a safe copy of the system window insets to pass through 254 * to the existing fitSystemWindows method and other similar internals. 255 * @hide 256 * 257 * @deprecated use {@link #getSystemWindowInsets()} instead. 258 */ 259 @Deprecated 260 @NonNull getSystemWindowInsetsAsRect()261 public Rect getSystemWindowInsetsAsRect() { 262 if (mTempRect == null) { 263 mTempRect = new Rect(); 264 } 265 Insets insets = getSystemWindowInsets(); 266 mTempRect.set(insets.left, insets.top, insets.right, insets.bottom); 267 return mTempRect; 268 } 269 270 /** 271 * Returns the system window insets in pixels. 272 * 273 * <p>The system window inset represents the area of a full-screen window that is 274 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 275 * </p> 276 * 277 * @return The system window insets 278 */ 279 @NonNull getSystemWindowInsets()280 public Insets getSystemWindowInsets() { 281 return getInsets(mTypeInsetsMap, compatSystemInsets()); 282 } 283 284 /** 285 * Returns the insets of a specific set of windows causing insets, denoted by the 286 * {@code typeMask} bit mask of {@link InsetType}s. 287 * 288 * @param typeMask Bit mask of {@link InsetType}s to query the insets for. 289 * @return The insets. 290 * 291 * @hide pending unhide 292 */ getInsets(@nsetType int typeMask)293 public Insets getInsets(@InsetType int typeMask) { 294 return getInsets(mTypeInsetsMap, typeMask); 295 } 296 297 /** 298 * Returns the maximum amount of insets a specific set of windows can cause, denoted by the 299 * {@code typeMask} bit mask of {@link InsetType}s. 300 * 301 * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially 302 * or fully obscured by the system window identified by {@code type}. This value does not 303 * change based on the visibility state of those elements. for example, if the status bar is 304 * normally shown, but temporarily hidden, the maximum inset will still provide the inset 305 * associated with the status bar being shown.</p> 306 * 307 * @param typeMask Bit mask of {@link InsetType}s to query the insets for. 308 * @return The insets. 309 * 310 * @throws IllegalArgumentException If the caller tries to query {@link Type#ime()}. Maximum 311 * insets are not available for this type as the height of the 312 * IME is dynamic depending on the {@link EditorInfo} of the 313 * currently focused view, as well as the UI state of the IME. 314 * @hide pending unhide 315 */ getMaxInsets(@nsetType int typeMask)316 public Insets getMaxInsets(@InsetType int typeMask) throws IllegalArgumentException { 317 if ((typeMask & IME) != 0) { 318 throw new IllegalArgumentException("Unable to query the maximum insets for IME"); 319 } 320 return getInsets(mTypeMaxInsetsMap, typeMask); 321 } 322 323 /** 324 * Returns whether a set of windows that may cause insets is currently visible on screen, 325 * regardless of whether it actually overlaps with this window. 326 * 327 * @param typeMask Bit mask of {@link InsetType}s to query visibility status. 328 * @return {@code true} if and only if all windows included in {@code typeMask} are currently 329 * visible on screen. 330 * @hide pending unhide 331 */ isVisible(@nsetType int typeMask)332 public boolean isVisible(@InsetType int typeMask) { 333 for (int i = FIRST; i <= LAST; i = i << 1) { 334 if ((typeMask & i) == 0) { 335 continue; 336 } 337 if (!mTypeVisibilityMap[indexOf(i)]) { 338 return false; 339 } 340 } 341 return true; 342 } 343 344 /** 345 * Returns the left system window inset in pixels. 346 * 347 * <p>The system window inset represents the area of a full-screen window that is 348 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 349 * </p> 350 * 351 * @return The left system window inset 352 */ getSystemWindowInsetLeft()353 public int getSystemWindowInsetLeft() { 354 return getSystemWindowInsets().left; 355 } 356 357 /** 358 * Returns the top system window inset in pixels. 359 * 360 * <p>The system window inset represents the area of a full-screen window that is 361 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 362 * </p> 363 * 364 * @return The top system window inset 365 */ getSystemWindowInsetTop()366 public int getSystemWindowInsetTop() { 367 return getSystemWindowInsets().top; 368 } 369 370 /** 371 * Returns the right system window inset in pixels. 372 * 373 * <p>The system window inset represents the area of a full-screen window that is 374 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 375 * </p> 376 * 377 * @return The right system window inset 378 */ getSystemWindowInsetRight()379 public int getSystemWindowInsetRight() { 380 return getSystemWindowInsets().right; 381 } 382 383 /** 384 * Returns the bottom system window inset in pixels. 385 * 386 * <p>The system window inset represents the area of a full-screen window that is 387 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 388 * </p> 389 * 390 * @return The bottom system window inset 391 */ getSystemWindowInsetBottom()392 public int getSystemWindowInsetBottom() { 393 return getSystemWindowInsets().bottom; 394 } 395 396 /** 397 * Returns true if this WindowInsets has nonzero system window insets. 398 * 399 * <p>The system window inset represents the area of a full-screen window that is 400 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 401 * </p> 402 * 403 * @return true if any of the system window inset values are nonzero 404 */ hasSystemWindowInsets()405 public boolean hasSystemWindowInsets() { 406 return !getSystemWindowInsets().equals(Insets.NONE); 407 } 408 409 /** 410 * Returns true if this WindowInsets has any nonzero insets. 411 * 412 * @return true if any inset values are nonzero 413 */ hasInsets()414 public boolean hasInsets() { 415 return !getInsets(mTypeInsetsMap, all()).equals(Insets.NONE) 416 || !getInsets(mTypeMaxInsetsMap, all()).equals(Insets.NONE) 417 || mDisplayCutout != null; 418 } 419 420 /** 421 * Returns the display cutout if there is one. 422 * 423 * @return the display cutout or null if there is none 424 * @see DisplayCutout 425 */ 426 @Nullable getDisplayCutout()427 public DisplayCutout getDisplayCutout() { 428 return mDisplayCutout; 429 } 430 431 /** 432 * Returns a copy of this WindowInsets with the cutout fully consumed. 433 * 434 * @return A modified copy of this WindowInsets 435 */ 436 @NonNull consumeDisplayCutout()437 public WindowInsets consumeDisplayCutout() { 438 return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, 439 mStableInsetsConsumed ? null : mTypeMaxInsetsMap, 440 mTypeVisibilityMap, 441 mIsRound, mAlwaysConsumeSystemBars, 442 null /* displayCutout */); 443 } 444 445 446 /** 447 * Check if these insets have been fully consumed. 448 * 449 * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods 450 * have been called such that all insets have been set to zero. This affects propagation of 451 * insets through the view hierarchy; insets that have not been fully consumed will continue 452 * to propagate down to child views.</p> 453 * 454 * <p>The result of this method is equivalent to the return value of 455 * {@link View#fitSystemWindows(android.graphics.Rect)}.</p> 456 * 457 * @return true if the insets have been fully consumed. 458 */ isConsumed()459 public boolean isConsumed() { 460 return mSystemWindowInsetsConsumed && mStableInsetsConsumed 461 && mDisplayCutoutConsumed; 462 } 463 464 /** 465 * Returns true if the associated window has a round shape. 466 * 467 * <p>A round window's left, top, right and bottom edges reach all the way to the 468 * associated edges of the window but the corners may not be visible. Views responding 469 * to round insets should take care to not lay out critical elements within the corners 470 * where they may not be accessible.</p> 471 * 472 * @return True if the window is round 473 */ isRound()474 public boolean isRound() { 475 return mIsRound; 476 } 477 478 /** 479 * Returns a copy of this WindowInsets with the system window insets fully consumed. 480 * 481 * @return A modified copy of this WindowInsets 482 */ 483 @NonNull consumeSystemWindowInsets()484 public WindowInsets consumeSystemWindowInsets() { 485 return new WindowInsets(null, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, 486 mTypeVisibilityMap, 487 mIsRound, mAlwaysConsumeSystemBars, 488 displayCutoutCopyConstructorArgument(this)); 489 } 490 491 // TODO(b/119190588): replace @code with @link below 492 /** 493 * Returns a copy of this WindowInsets with selected system window insets replaced 494 * with new values. 495 * 496 * <p>Note: If the system window insets are already consumed, this method will return them 497 * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to 498 * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of 499 * whether they were consumed, and this method returns invalid non-zero consumed insets. 500 * 501 * @param left New left inset in pixels 502 * @param top New top inset in pixels 503 * @param right New right inset in pixels 504 * @param bottom New bottom inset in pixels 505 * @return A modified copy of this WindowInsets 506 * @deprecated use {@code Builder#Builder(WindowInsets)} with 507 * {@link Builder#setSystemWindowInsets(Insets)} instead. 508 */ 509 @Deprecated 510 @NonNull replaceSystemWindowInsets(int left, int top, int right, int bottom)511 public WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) { 512 // Compat edge case: what should this do if the insets have already been consumed? 513 // On platforms prior to Q, the behavior was to override the insets with non-zero values, 514 // but leave them consumed, which is invalid (consumed insets must be zero). 515 // The behavior is now keeping them consumed and discarding the new insets. 516 if (mSystemWindowInsetsConsumed) { 517 return this; 518 } 519 return new Builder(this).setSystemWindowInsets(Insets.of(left, top, right, bottom)).build(); 520 } 521 522 // TODO(b/119190588): replace @code with @link below 523 /** 524 * Returns a copy of this WindowInsets with selected system window insets replaced 525 * with new values. 526 * 527 * <p>Note: If the system window insets are already consumed, this method will return them 528 * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to 529 * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of 530 * whether they were consumed, and this method returns invalid non-zero consumed insets. 531 * 532 * @param systemWindowInsets New system window insets. Each field is the inset in pixels 533 * for that edge 534 * @return A modified copy of this WindowInsets 535 * @deprecated use {@code Builder#Builder(WindowInsets)} with 536 * {@link Builder#setSystemWindowInsets(Insets)} instead. 537 */ 538 @Deprecated 539 @NonNull replaceSystemWindowInsets(Rect systemWindowInsets)540 public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) { 541 return replaceSystemWindowInsets(systemWindowInsets.left, systemWindowInsets.top, 542 systemWindowInsets.right, systemWindowInsets.bottom); 543 } 544 545 /** 546 * Returns the stable insets in pixels. 547 * 548 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 549 * partially or fully obscured by the system UI elements. This value does not change 550 * based on the visibility state of those elements; for example, if the status bar is 551 * normally shown, but temporarily hidden, the stable inset will still provide the inset 552 * associated with the status bar being shown.</p> 553 * 554 * @return The stable insets 555 */ 556 @NonNull getStableInsets()557 public Insets getStableInsets() { 558 return getInsets(mTypeMaxInsetsMap, compatSystemInsets()); 559 } 560 561 /** 562 * Returns the top stable inset in pixels. 563 * 564 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 565 * partially or fully obscured by the system UI elements. This value does not change 566 * based on the visibility state of those elements; for example, if the status bar is 567 * normally shown, but temporarily hidden, the stable inset will still provide the inset 568 * associated with the status bar being shown.</p> 569 * 570 * @return The top stable inset 571 */ getStableInsetTop()572 public int getStableInsetTop() { 573 return getStableInsets().top; 574 } 575 576 /** 577 * Returns the left stable inset in pixels. 578 * 579 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 580 * partially or fully obscured by the system UI elements. This value does not change 581 * based on the visibility state of those elements; for example, if the status bar is 582 * normally shown, but temporarily hidden, the stable inset will still provide the inset 583 * associated with the status bar being shown.</p> 584 * 585 * @return The left stable inset 586 */ getStableInsetLeft()587 public int getStableInsetLeft() { 588 return getStableInsets().left; 589 } 590 591 /** 592 * Returns the right stable inset in pixels. 593 * 594 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 595 * partially or fully obscured by the system UI elements. This value does not change 596 * based on the visibility state of those elements; for example, if the status bar is 597 * normally shown, but temporarily hidden, the stable inset will still provide the inset 598 * associated with the status bar being shown.</p> 599 * 600 * @return The right stable inset 601 */ getStableInsetRight()602 public int getStableInsetRight() { 603 return getStableInsets().right; 604 } 605 606 /** 607 * Returns the bottom stable inset in pixels. 608 * 609 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 610 * partially or fully obscured by the system UI elements. This value does not change 611 * based on the visibility state of those elements; for example, if the status bar is 612 * normally shown, but temporarily hidden, the stable inset will still provide the inset 613 * associated with the status bar being shown.</p> 614 * 615 * @return The bottom stable inset 616 */ getStableInsetBottom()617 public int getStableInsetBottom() { 618 return getStableInsets().bottom; 619 } 620 621 /** 622 * Returns true if this WindowInsets has nonzero stable insets. 623 * 624 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 625 * partially or fully obscured by the system UI elements. This value does not change 626 * based on the visibility state of those elements; for example, if the status bar is 627 * normally shown, but temporarily hidden, the stable inset will still provide the inset 628 * associated with the status bar being shown.</p> 629 * 630 * @return true if any of the stable inset values are nonzero 631 */ hasStableInsets()632 public boolean hasStableInsets() { 633 return !getStableInsets().equals(Insets.NONE); 634 } 635 636 /** 637 * Returns the system gesture insets. 638 * 639 * <p>The system gesture insets represent the area of a window where system gestures have 640 * priority and may consume some or all touch input, e.g. due to the a system bar 641 * occupying it, or it being reserved for touch-only gestures. 642 * 643 * <p>An app can declare priority over system gestures with 644 * {@link View#setSystemGestureExclusionRects} outside of the 645 * {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}. 646 * 647 * <p>Simple taps are guaranteed to reach the window even within the system gesture insets, 648 * as long as they are outside the {@link #getTappableElementInsets() system window insets}. 649 * 650 * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned 651 * even when the system gestures are inactive due to 652 * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or 653 * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}. 654 * 655 * <p>This inset is consumed together with the {@link #getSystemWindowInsets() 656 * system window insets} by {@link #consumeSystemWindowInsets()}. 657 * 658 * @see #getMandatorySystemGestureInsets 659 */ 660 @NonNull getSystemGestureInsets()661 public Insets getSystemGestureInsets() { 662 return getInsets(mTypeInsetsMap, SYSTEM_GESTURES); 663 } 664 665 /** 666 * Returns the mandatory system gesture insets. 667 * 668 * <p>The mandatory system gesture insets represent the area of a window where mandatory system 669 * gestures have priority and may consume some or all touch input, e.g. due to the a system bar 670 * occupying it, or it being reserved for touch-only gestures. 671 * 672 * <p>In contrast to {@link #getSystemGestureInsets regular system gestures}, <b>mandatory</b> 673 * system gestures cannot be overriden by {@link View#setSystemGestureExclusionRects}. 674 * 675 * <p>Simple taps are guaranteed to reach the window even within the system gesture insets, 676 * as long as they are outside the {@link #getTappableElementInsets() system window insets}. 677 * 678 * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned 679 * even when the system gestures are inactive due to 680 * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or 681 * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}. 682 * 683 * <p>This inset is consumed together with the {@link #getSystemWindowInsets() 684 * system window insets} by {@link #consumeSystemWindowInsets()}. 685 * 686 * @see #getSystemGestureInsets 687 */ 688 @NonNull getMandatorySystemGestureInsets()689 public Insets getMandatorySystemGestureInsets() { 690 return getInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES); 691 } 692 693 /** 694 * Returns the tappable element insets. 695 * 696 * <p>The tappable element insets represent how much tappable elements <b>must at least</b> be 697 * inset to remain both tappable and visually unobstructed by persistent system windows. 698 * 699 * <p>This may be smaller than {@link #getSystemWindowInsets()} if the system window is 700 * largely transparent and lets through simple taps (but not necessarily more complex gestures). 701 * 702 * <p>Note that generally, tappable elements <strong>should</strong> be aligned with the 703 * {@link #getSystemWindowInsets() system window insets} instead to avoid overlapping with the 704 * system bars. 705 * 706 * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned 707 * even when the area covered by the inset would be tappable due to 708 * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or 709 * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}. 710 * 711 * <p>This inset is consumed together with the {@link #getSystemWindowInsets() 712 * system window insets} by {@link #consumeSystemWindowInsets()}. 713 */ 714 @NonNull getTappableElementInsets()715 public Insets getTappableElementInsets() { 716 return getInsets(mTypeInsetsMap, TAPPABLE_ELEMENT); 717 } 718 719 /** 720 * Returns a copy of this WindowInsets with the stable insets fully consumed. 721 * 722 * @return A modified copy of this WindowInsets 723 */ 724 @NonNull consumeStableInsets()725 public WindowInsets consumeStableInsets() { 726 return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, null, 727 mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars, 728 displayCutoutCopyConstructorArgument(this)); 729 } 730 731 /** 732 * @hide 733 */ shouldAlwaysConsumeSystemBars()734 public boolean shouldAlwaysConsumeSystemBars() { 735 return mAlwaysConsumeSystemBars; 736 } 737 738 @Override toString()739 public String toString() { 740 return "WindowInsets{systemWindowInsets=" + getSystemWindowInsets() 741 + " stableInsets=" + getStableInsets() 742 + " sysGestureInsets=" + getSystemGestureInsets() 743 + (mDisplayCutout != null ? " cutout=" + mDisplayCutout : "") 744 + (isRound() ? " round" : "") 745 + "}"; 746 } 747 748 /** 749 * Returns a copy of this instance inset in the given directions. 750 * 751 * @see #inset(int, int, int, int) 752 * @deprecated use {@link #inset(Insets)} 753 * @hide 754 */ 755 @Deprecated 756 @NonNull inset(Rect r)757 public WindowInsets inset(Rect r) { 758 return inset(r.left, r.top, r.right, r.bottom); 759 } 760 761 /** 762 * Returns a copy of this instance inset in the given directions. 763 * 764 * @see #inset(int, int, int, int) 765 * @hide 766 */ 767 @NonNull inset(Insets insets)768 public WindowInsets inset(Insets insets) { 769 return inset(insets.left, insets.top, insets.right, insets.bottom); 770 } 771 772 /** 773 * Returns a copy of this instance inset in the given directions. 774 * 775 * This is intended for dispatching insets to areas of the window that are smaller than the 776 * current area. 777 * 778 * <p>Example: 779 * <pre> 780 * childView.dispatchApplyWindowInsets(insets.inset( 781 * childMarginLeft, childMarginTop, childMarginBottom, childMarginRight)); 782 * </pre> 783 * 784 * @param left the amount of insets to remove from the left. Must be non-negative. 785 * @param top the amount of insets to remove from the top. Must be non-negative. 786 * @param right the amount of insets to remove from the right. Must be non-negative. 787 * @param bottom the amount of insets to remove from the bottom. Must be non-negative. 788 * 789 * @return the inset insets 790 */ 791 @NonNull inset(@ntRangefrom = 0) int left, @IntRange(from = 0) int top, @IntRange(from = 0) int right, @IntRange(from = 0) int bottom)792 public WindowInsets inset(@IntRange(from = 0) int left, @IntRange(from = 0) int top, 793 @IntRange(from = 0) int right, @IntRange(from = 0) int bottom) { 794 Preconditions.checkArgumentNonnegative(left); 795 Preconditions.checkArgumentNonnegative(top); 796 Preconditions.checkArgumentNonnegative(right); 797 Preconditions.checkArgumentNonnegative(bottom); 798 799 return new WindowInsets( 800 mSystemWindowInsetsConsumed 801 ? null 802 : insetInsets(mTypeInsetsMap, left, top, right, bottom), 803 mStableInsetsConsumed 804 ? null 805 : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom), 806 mTypeVisibilityMap, 807 mIsRound, mAlwaysConsumeSystemBars, 808 mDisplayCutoutConsumed 809 ? null 810 : mDisplayCutout == null 811 ? DisplayCutout.NO_CUTOUT 812 : mDisplayCutout.inset(left, top, right, bottom)); 813 } 814 815 @Override equals(Object o)816 public boolean equals(Object o) { 817 if (this == o) return true; 818 if (o == null || !(o instanceof WindowInsets)) return false; 819 WindowInsets that = (WindowInsets) o; 820 821 return mIsRound == that.mIsRound 822 && mAlwaysConsumeSystemBars == that.mAlwaysConsumeSystemBars 823 && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed 824 && mStableInsetsConsumed == that.mStableInsetsConsumed 825 && mDisplayCutoutConsumed == that.mDisplayCutoutConsumed 826 && Arrays.equals(mTypeInsetsMap, that.mTypeInsetsMap) 827 && Arrays.equals(mTypeMaxInsetsMap, that.mTypeMaxInsetsMap) 828 && Arrays.equals(mTypeVisibilityMap, that.mTypeVisibilityMap) 829 && Objects.equals(mDisplayCutout, that.mDisplayCutout); 830 } 831 832 @Override hashCode()833 public int hashCode() { 834 return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap), 835 Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, 836 mAlwaysConsumeSystemBars, mSystemWindowInsetsConsumed, mStableInsetsConsumed, 837 mDisplayCutoutConsumed); 838 } 839 840 841 /** 842 * Insets every inset in {@code typeInsetsMap} by the specified left, top, right, bottom. 843 * 844 * @return {@code typeInsetsMap} if no inset was modified; a copy of the map with the modified 845 * insets otherwise. 846 */ insetInsets( Insets[] typeInsetsMap, int left, int top, int right, int bottom)847 private static Insets[] insetInsets( 848 Insets[] typeInsetsMap, int left, int top, int right, int bottom) { 849 boolean cloned = false; 850 for (int i = 0; i < SIZE; i++) { 851 Insets insets = typeInsetsMap[i]; 852 if (insets == null) { 853 continue; 854 } 855 Insets insetInsets = insetInsets(insets, left, top, right, bottom); 856 if (insetInsets != insets) { 857 if (!cloned) { 858 typeInsetsMap = typeInsetsMap.clone(); 859 cloned = true; 860 } 861 typeInsetsMap[i] = insetInsets; 862 } 863 } 864 return typeInsetsMap; 865 } 866 insetInsets(Insets insets, int left, int top, int right, int bottom)867 private static Insets insetInsets(Insets insets, int left, int top, int right, int bottom) { 868 int newLeft = Math.max(0, insets.left - left); 869 int newTop = Math.max(0, insets.top - top); 870 int newRight = Math.max(0, insets.right - right); 871 int newBottom = Math.max(0, insets.bottom - bottom); 872 if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) { 873 return insets; 874 } 875 return Insets.of(newLeft, newTop, newRight, newBottom); 876 } 877 878 /** 879 * @return whether system window insets have been consumed. 880 */ isSystemWindowInsetsConsumed()881 boolean isSystemWindowInsetsConsumed() { 882 return mSystemWindowInsetsConsumed; 883 } 884 885 /** 886 * Builder for WindowInsets. 887 */ 888 public static final class Builder { 889 890 private final Insets[] mTypeInsetsMap; 891 private final Insets[] mTypeMaxInsetsMap; 892 private final boolean[] mTypeVisibilityMap; 893 private boolean mSystemInsetsConsumed = true; 894 private boolean mStableInsetsConsumed = true; 895 896 private DisplayCutout mDisplayCutout; 897 898 private boolean mIsRound; 899 private boolean mAlwaysConsumeSystemBars; 900 901 /** 902 * Creates a builder where all insets are initially consumed. 903 */ Builder()904 public Builder() { 905 mTypeInsetsMap = new Insets[SIZE]; 906 mTypeMaxInsetsMap = new Insets[SIZE]; 907 mTypeVisibilityMap = new boolean[SIZE]; 908 } 909 910 /** 911 * Creates a builder where all insets are initialized from {@link WindowInsets}. 912 * 913 * @param insets the instance to initialize from. 914 */ Builder(@onNull WindowInsets insets)915 public Builder(@NonNull WindowInsets insets) { 916 mTypeInsetsMap = insets.mTypeInsetsMap.clone(); 917 mTypeMaxInsetsMap = insets.mTypeMaxInsetsMap.clone(); 918 mTypeVisibilityMap = insets.mTypeVisibilityMap.clone(); 919 mSystemInsetsConsumed = insets.mSystemWindowInsetsConsumed; 920 mStableInsetsConsumed = insets.mStableInsetsConsumed; 921 mDisplayCutout = displayCutoutCopyConstructorArgument(insets); 922 mIsRound = insets.mIsRound; 923 mAlwaysConsumeSystemBars = insets.mAlwaysConsumeSystemBars; 924 } 925 926 /** 927 * Sets system window insets in pixels. 928 * 929 * <p>The system window inset represents the area of a full-screen window that is 930 * partially or fully obscured by the status bar, navigation bar, IME or other system 931 * windows.</p> 932 * 933 * @see #getSystemWindowInsets() 934 * @return itself 935 */ 936 @NonNull setSystemWindowInsets(@onNull Insets systemWindowInsets)937 public Builder setSystemWindowInsets(@NonNull Insets systemWindowInsets) { 938 Preconditions.checkNotNull(systemWindowInsets); 939 assignCompatInsets(mTypeInsetsMap, systemWindowInsets.toRect()); 940 mSystemInsetsConsumed = false; 941 return this; 942 } 943 944 /** 945 * Sets system gesture insets in pixels. 946 * 947 * <p>The system gesture insets represent the area of a window where system gestures have 948 * priority and may consume some or all touch input, e.g. due to the a system bar 949 * occupying it, or it being reserved for touch-only gestures. 950 * 951 * @see #getSystemGestureInsets() 952 * @return itself 953 */ 954 @NonNull setSystemGestureInsets(@onNull Insets insets)955 public Builder setSystemGestureInsets(@NonNull Insets insets) { 956 WindowInsets.setInsets(mTypeInsetsMap, SYSTEM_GESTURES, insets); 957 return this; 958 } 959 960 /** 961 * Sets mandatory system gesture insets in pixels. 962 * 963 * <p>The mandatory system gesture insets represent the area of a window where mandatory 964 * system gestures have priority and may consume some or all touch input, e.g. due to the a 965 * system bar occupying it, or it being reserved for touch-only gestures. 966 * 967 * <p>In contrast to {@link #setSystemGestureInsets regular system gestures}, 968 * <b>mandatory</b> system gestures cannot be overriden by 969 * {@link View#setSystemGestureExclusionRects}. 970 * 971 * @see #getMandatorySystemGestureInsets() 972 * @return itself 973 */ 974 @NonNull setMandatorySystemGestureInsets(@onNull Insets insets)975 public Builder setMandatorySystemGestureInsets(@NonNull Insets insets) { 976 WindowInsets.setInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES, insets); 977 return this; 978 } 979 980 /** 981 * Sets tappable element insets in pixels. 982 * 983 * <p>The tappable element insets represent how much tappable elements <b>must at least</b> 984 * be inset to remain both tappable and visually unobstructed by persistent system windows. 985 * 986 * @see #getTappableElementInsets() 987 * @return itself 988 */ 989 @NonNull setTappableElementInsets(@onNull Insets insets)990 public Builder setTappableElementInsets(@NonNull Insets insets) { 991 WindowInsets.setInsets(mTypeInsetsMap, TAPPABLE_ELEMENT, insets); 992 return this; 993 } 994 995 /** 996 * Sets the insets of a specific window type in pixels. 997 * 998 * <p>The insets represents the area of a a window that is partially or fully obscured by 999 * the system windows identified by {@code typeMask}. 1000 * </p> 1001 * 1002 * @see #getInsets(int) 1003 * 1004 * @param typeMask The bitmask of {@link InsetType} to set the insets for. 1005 * @param insets The insets to set. 1006 * 1007 * @return itself 1008 * @hide pending unhide 1009 */ 1010 @NonNull setInsets(@nsetType int typeMask, @NonNull Insets insets)1011 public Builder setInsets(@InsetType int typeMask, @NonNull Insets insets) { 1012 Preconditions.checkNotNull(insets); 1013 WindowInsets.setInsets(mTypeInsetsMap, typeMask, insets); 1014 mSystemInsetsConsumed = false; 1015 return this; 1016 } 1017 1018 /** 1019 * Sets the maximum amount of insets a specific window type in pixels. 1020 * 1021 * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially 1022 * or fully obscured by the system windows identified by {@code typeMask}. This value does 1023 * not change based on the visibility state of those elements. for example, if the status 1024 * bar is normally shown, but temporarily hidden, the maximum inset will still provide the 1025 * inset associated with the status bar being shown.</p> 1026 * 1027 * @see #getMaxInsets(int) 1028 * 1029 * @param typeMask The bitmask of {@link InsetType} to set the insets for. 1030 * @param insets The insets to set. 1031 * 1032 * @return itself 1033 * 1034 * @throws IllegalArgumentException If {@code typeMask} contains {@link Type#ime()}. Maximum 1035 * insets are not available for this type as the height of 1036 * the IME is dynamic depending on the {@link EditorInfo} 1037 * of the currently focused view, as well as the UI 1038 * state of the IME. 1039 * @hide pending unhide 1040 */ 1041 @NonNull setMaxInsets(@nsetType int typeMask, @NonNull Insets insets)1042 public Builder setMaxInsets(@InsetType int typeMask, @NonNull Insets insets) 1043 throws IllegalArgumentException{ 1044 if (typeMask == IME) { 1045 throw new IllegalArgumentException("Maximum inset not available for IME"); 1046 } 1047 Preconditions.checkNotNull(insets); 1048 WindowInsets.setInsets(mTypeMaxInsetsMap, typeMask, insets); 1049 mStableInsetsConsumed = false; 1050 return this; 1051 } 1052 1053 /** 1054 * Sets whether windows that can cause insets are currently visible on screen. 1055 * 1056 * 1057 * @see #isVisible(int) 1058 * 1059 * @param typeMask The bitmask of {@link InsetType} to set the visibility for. 1060 * @param visible Whether to mark the windows as visible or not. 1061 * 1062 * @return itself 1063 * @hide pending unhide 1064 */ 1065 @NonNull setVisible(@nsetType int typeMask, boolean visible)1066 public Builder setVisible(@InsetType int typeMask, boolean visible) { 1067 for (int i = FIRST; i <= LAST; i = i << 1) { 1068 if ((typeMask & i) == 0) { 1069 continue; 1070 } 1071 mTypeVisibilityMap[indexOf(i)] = visible; 1072 } 1073 return this; 1074 } 1075 1076 /** 1077 * Sets the stable insets in pixels. 1078 * 1079 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 1080 * partially or fully obscured by the system UI elements. This value does not change 1081 * based on the visibility state of those elements; for example, if the status bar is 1082 * normally shown, but temporarily hidden, the stable inset will still provide the inset 1083 * associated with the status bar being shown.</p> 1084 * 1085 * @see #getStableInsets() 1086 * @return itself 1087 */ 1088 @NonNull setStableInsets(@onNull Insets stableInsets)1089 public Builder setStableInsets(@NonNull Insets stableInsets) { 1090 Preconditions.checkNotNull(stableInsets); 1091 assignCompatInsets(mTypeMaxInsetsMap, stableInsets.toRect()); 1092 mStableInsetsConsumed = false; 1093 return this; 1094 } 1095 1096 /** 1097 * Sets the display cutout. 1098 * 1099 * @see #getDisplayCutout() 1100 * @param displayCutout the display cutout or null if there is none 1101 * @return itself 1102 */ 1103 @NonNull setDisplayCutout(@ullable DisplayCutout displayCutout)1104 public Builder setDisplayCutout(@Nullable DisplayCutout displayCutout) { 1105 mDisplayCutout = displayCutout != null ? displayCutout : DisplayCutout.NO_CUTOUT; 1106 return this; 1107 } 1108 1109 /** @hide */ 1110 @NonNull setRound(boolean round)1111 public Builder setRound(boolean round) { 1112 mIsRound = round; 1113 return this; 1114 } 1115 1116 /** @hide */ 1117 @NonNull setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars)1118 public Builder setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars) { 1119 mAlwaysConsumeSystemBars = alwaysConsumeSystemBars; 1120 return this; 1121 } 1122 1123 /** 1124 * Builds a {@link WindowInsets} instance. 1125 * 1126 * @return the {@link WindowInsets} instance. 1127 */ 1128 @NonNull build()1129 public WindowInsets build() { 1130 return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap, 1131 mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, 1132 mIsRound, mAlwaysConsumeSystemBars, mDisplayCutout); 1133 } 1134 } 1135 1136 /** 1137 * Class that defines different types of sources causing window insets. 1138 * @hide pending unhide 1139 */ 1140 public static final class Type { 1141 1142 static final int FIRST = 1 << 0; 1143 static final int TOP_BAR = FIRST; 1144 1145 static final int IME = 1 << 1; 1146 static final int SIDE_BARS = 1 << 2; 1147 1148 static final int SYSTEM_GESTURES = 1 << 3; 1149 static final int MANDATORY_SYSTEM_GESTURES = 1 << 4; 1150 static final int TAPPABLE_ELEMENT = 1 << 5; 1151 1152 static final int LAST = 1 << 6; 1153 static final int SIZE = 7; 1154 static final int WINDOW_DECOR = LAST; 1155 indexOf(@nsetType int type)1156 static int indexOf(@InsetType int type) { 1157 switch (type) { 1158 case TOP_BAR: 1159 return 0; 1160 case IME: 1161 return 1; 1162 case SIDE_BARS: 1163 return 2; 1164 case SYSTEM_GESTURES: 1165 return 3; 1166 case MANDATORY_SYSTEM_GESTURES: 1167 return 4; 1168 case TAPPABLE_ELEMENT: 1169 return 5; 1170 case WINDOW_DECOR: 1171 return 6; 1172 default: 1173 throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST," 1174 + " type=" + type); 1175 } 1176 } 1177 Type()1178 private Type() { 1179 } 1180 1181 /** @hide */ 1182 @Retention(RetentionPolicy.SOURCE) 1183 @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES, 1184 MANDATORY_SYSTEM_GESTURES, TAPPABLE_ELEMENT}) 1185 public @interface InsetType { 1186 } 1187 1188 /** 1189 * @return An inset type representing the top bar of a window, which can be the status 1190 * bar on handheld-like devices as well as a caption bar. 1191 */ topBar()1192 public static @InsetType int topBar() { 1193 return TOP_BAR; 1194 } 1195 1196 /** 1197 * @return An inset type representing the window of an {@link InputMethod}. 1198 */ ime()1199 public static @InsetType int ime() { 1200 return IME; 1201 } 1202 1203 /** 1204 * @return An inset type representing any system bars that are not {@link #topBar()}. 1205 */ sideBars()1206 public static @InsetType int sideBars() { 1207 return SIDE_BARS; 1208 } 1209 1210 /** 1211 * @return An inset type representing decor that is being app-controlled. 1212 */ windowDecor()1213 public static @InsetType int windowDecor() { 1214 return WINDOW_DECOR; 1215 } 1216 1217 /** 1218 * Returns an inset type representing the system gesture insets. 1219 * 1220 * <p>The system gesture insets represent the area of a window where system gestures have 1221 * priority and may consume some or all touch input, e.g. due to the a system bar 1222 * occupying it, or it being reserved for touch-only gestures. 1223 * 1224 * <p>Simple taps are guaranteed to reach the window even within the system gesture insets, 1225 * as long as they are outside the {@link #getSystemWindowInsets() system window insets}. 1226 * 1227 * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned 1228 * even when the system gestures are inactive due to 1229 * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or 1230 * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}. 1231 * 1232 * @see #getSystemGestureInsets() 1233 */ systemGestures()1234 public static @InsetType int systemGestures() { 1235 return SYSTEM_GESTURES; 1236 } 1237 1238 /** 1239 * @see #getMandatorySystemGestureInsets 1240 */ mandatorySystemGestures()1241 public static @InsetType int mandatorySystemGestures() { 1242 return MANDATORY_SYSTEM_GESTURES; 1243 } 1244 1245 /** 1246 * @see #getTappableElementInsets 1247 */ tappableElement()1248 public static @InsetType int tappableElement() { 1249 return TAPPABLE_ELEMENT; 1250 } 1251 1252 /** 1253 * @return All system bars. Includes {@link #topBar()} as well as {@link #sideBars()}, but 1254 * not {@link #ime()}. 1255 */ systemBars()1256 public static @InsetType int systemBars() { 1257 return TOP_BAR | SIDE_BARS; 1258 } 1259 1260 /** 1261 * @return Inset types representing the list of bars that traditionally were denoted as 1262 * system insets. 1263 * @hide 1264 */ compatSystemInsets()1265 static @InsetType int compatSystemInsets() { 1266 return TOP_BAR | SIDE_BARS | IME; 1267 } 1268 1269 /** 1270 * @return All inset types combined. 1271 * 1272 * TODO: Figure out if this makes sense at all, mixing e.g {@link #systemGestures()} and 1273 * {@link #ime()} does not seem very useful. 1274 */ all()1275 public static @InsetType int all() { 1276 return 0xFFFFFFFF; 1277 } 1278 } 1279 } 1280