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