diff --git a/api/current.txt b/api/current.txt index 79a909d3bed3d..d48b561746f62 100644 --- a/api/current.txt +++ b/api/current.txt @@ -51957,6 +51957,7 @@ package android.view { method @NonNull public android.view.WindowInsets consumeStableInsets(); method @NonNull public android.view.WindowInsets consumeSystemWindowInsets(); method @Nullable public android.view.DisplayCutout getDisplayCutout(); + method @NonNull public android.graphics.Insets getMandatorySystemGestureInsets(); method public int getStableInsetBottom(); method public int getStableInsetLeft(); method public int getStableInsetRight(); @@ -51968,6 +51969,7 @@ package android.view { method public int getSystemWindowInsetRight(); method public int getSystemWindowInsetTop(); method @NonNull public android.graphics.Insets getSystemWindowInsets(); + method @NonNull public android.graphics.Insets getTappableElementInsets(); method public boolean hasInsets(); method public boolean hasStableInsets(); method public boolean hasSystemWindowInsets(); @@ -51983,9 +51985,11 @@ package android.view { ctor public WindowInsets.Builder(@NonNull android.view.WindowInsets); method @NonNull public android.view.WindowInsets build(); method @NonNull public android.view.WindowInsets.Builder setDisplayCutout(@Nullable android.view.DisplayCutout); + method @NonNull public android.view.WindowInsets.Builder setMandatorySystemGestureInsets(@NonNull android.graphics.Insets); method @NonNull public android.view.WindowInsets.Builder setStableInsets(@NonNull android.graphics.Insets); method @NonNull public android.view.WindowInsets.Builder setSystemGestureInsets(@NonNull android.graphics.Insets); method @NonNull public android.view.WindowInsets.Builder setSystemWindowInsets(@NonNull android.graphics.Insets); + method @NonNull public android.view.WindowInsets.Builder setTappableElementInsets(@NonNull android.graphics.Insets); } public interface WindowManager extends android.view.ViewManager { diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 2d7e17961279b..6129b38104af1 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -145,7 +145,14 @@ public class InsetsState implements Parcelable { // TODO: set system gesture insets based on actual system gesture area. typeInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets); - typeMaxInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets); + typeInsetsMap[Type.indexOf(Type.mandatorySystemGestures())] = + Insets.of(legacyContentInsets); + typeInsetsMap[Type.indexOf(Type.tappableElement())] = Insets.of(legacyContentInsets); + + typeMaxInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyStableInsets); + typeMaxInsetsMap[Type.indexOf(Type.mandatorySystemGestures())] = + Insets.of(legacyStableInsets); + typeMaxInsetsMap[Type.indexOf(Type.tappableElement())] = Insets.of(legacyStableInsets); } for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { InsetsSource source = mSources.get(type); diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index f1a992cb45fac..aac0e34de0da0 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -20,14 +20,18 @@ package android.view; import static android.view.WindowInsets.Type.FIRST; import static android.view.WindowInsets.Type.IME; import static android.view.WindowInsets.Type.LAST; +import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES; import static android.view.WindowInsets.Type.SIDE_BARS; import static android.view.WindowInsets.Type.SIZE; import static android.view.WindowInsets.Type.SYSTEM_GESTURES; +import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT; import static android.view.WindowInsets.Type.TOP_BAR; import static android.view.WindowInsets.Type.all; import static android.view.WindowInsets.Type.compatSystemInsets; import static android.view.WindowInsets.Type.indexOf; +import static android.view.WindowInsets.Type.mandatorySystemGestures; import static android.view.WindowInsets.Type.systemGestures; +import static android.view.WindowInsets.Type.tappableElement; import android.annotation.IntDef; import android.annotation.IntRange; @@ -223,6 +227,8 @@ public final class WindowInsets { assignCompatInsets(typeInsetMap, insets); // TODO: set system gesture insets based on actual system gesture area. typeInsetMap[indexOf(systemGestures())] = Insets.of(insets); + typeInsetMap[indexOf(mandatorySystemGestures())] = Insets.of(insets); + typeInsetMap[indexOf(tappableElement())] = Insets.of(insets); return typeInsetMap; } @@ -639,21 +645,82 @@ public final class WindowInsets { * priority and may consume some or all touch input, e.g. due to the a system bar * occupying it, or it being reserved for touch-only gestures. * + *

An app can declare priority over system gestures with + * {@link View#setSystemGestureExclusionRects} outside of the + * {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}. + * *

Simple taps are guaranteed to reach the window even within the system gesture insets, - * as long as they are outside the {@link #getSystemWindowInsets() system window insets}. + * as long as they are outside the {@link #getTappableElementInsets() system window insets}. * *

When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned * even when the system gestures are inactive due to * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}. * - *

This inset does not affect the result of {@link #isConsumed()} and cannot be consumed. + *

This inset is consumed together with the {@link #getSystemWindowInsets() + * system window insets} by {@link #consumeSystemWindowInsets()}. + * + * @see #getMandatorySystemGestureInsets */ @NonNull public Insets getSystemGestureInsets() { return getInsets(mTypeInsetsMap, SYSTEM_GESTURES); } + /** + * Returns the mandatory system gesture insets. + * + *

The mandatory system gesture insets represent the area of a window where mandatory system + * gestures have priority and may consume some or all touch input, e.g. due to the a system bar + * occupying it, or it being reserved for touch-only gestures. + * + *

In contrast to {@link #getSystemGestureInsets regular system gestures}, mandatory + * system gestures cannot be overriden by {@link View#setSystemGestureExclusionRects}. + * + *

Simple taps are guaranteed to reach the window even within the system gesture insets, + * as long as they are outside the {@link #getTappableElementInsets() system window insets}. + * + *

When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned + * even when the system gestures are inactive due to + * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or + * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}. + * + *

This inset is consumed together with the {@link #getSystemWindowInsets() + * system window insets} by {@link #consumeSystemWindowInsets()}. + * + * @see #getSystemGestureInsets + */ + @NonNull + public Insets getMandatorySystemGestureInsets() { + return getInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES); + } + + /** + * Returns the tappable element insets. + * + *

The tappable element insets represent how much tappable elements must at least be + * inset to remain both tappable and visually unobstructed by persistent system windows. + * + *

This may be smaller than {@link #getSystemWindowInsets()} if the system window is + * largely transparent and lets through simple taps (but not necessarily more complex gestures). + * + *

Note that generally, tappable elements should be aligned with the + * {@link #getSystemWindowInsets() system window insets} instead to avoid overlapping with the + * system bars. + * + *

When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned + * even when the area covered by the inset would be tappable due to + * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or + * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}. + * + *

This inset is consumed together with the {@link #getSystemWindowInsets() + * system window insets} by {@link #consumeSystemWindowInsets()}. + */ + @NonNull + public Insets getTappableElementInsets() { + return getInsets(mTypeInsetsMap, TAPPABLE_ELEMENT); + } + /** * Returns a copy of this WindowInsets with the stable insets fully consumed. * @@ -894,6 +961,41 @@ public final class WindowInsets { return this; } + /** + * Sets mandatory system gesture insets in pixels. + * + *

The mandatory system gesture insets represent the area of a window where mandatory + * system gestures have priority and may consume some or all touch input, e.g. due to the a + * system bar occupying it, or it being reserved for touch-only gestures. + * + *

In contrast to {@link #setSystemGestureInsets regular system gestures}, + * mandatory system gestures cannot be overriden by + * {@link View#setSystemGestureExclusionRects}. + * + * @see #getMandatorySystemGestureInsets() + * @return itself + */ + @NonNull + public Builder setMandatorySystemGestureInsets(@NonNull Insets insets) { + WindowInsets.setInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES, insets); + return this; + } + + /** + * Sets tappable element insets in pixels. + * + *

The tappable element insets represent how much tappable elements must at least + * be inset to remain both tappable and visually unobstructed by persistent system windows. + * + * @see #getTappableElementInsets() + * @return itself + */ + @NonNull + public Builder setTappableElementInsets(@NonNull Insets insets) { + WindowInsets.setInsets(mTypeInsetsMap, TAPPABLE_ELEMENT, insets); + return this; + } + /** * Sets the insets of a specific window type in pixels. * @@ -1041,16 +1143,18 @@ public final class WindowInsets { */ public static final class Type { - static final int FIRST = 0x1; + static final int FIRST = 1 << 0; static final int TOP_BAR = FIRST; - static final int IME = 0x2; - static final int SIDE_BARS = 0x4; + static final int IME = 1 << 1; + static final int SIDE_BARS = 1 << 2; - static final int SYSTEM_GESTURES = 0x8; + static final int SYSTEM_GESTURES = 1 << 3; + static final int MANDATORY_SYSTEM_GESTURES = 1 << 4; + static final int TAPPABLE_ELEMENT = 1 << 5; - static final int LAST = 0x10; - static final int SIZE = 5; + static final int LAST = 1 << 6; + static final int SIZE = 7; static final int WINDOW_DECOR = LAST; static int indexOf(@InsetType int type) { @@ -1063,8 +1167,12 @@ public final class WindowInsets { return 2; case SYSTEM_GESTURES: return 3; - case WINDOW_DECOR: + case MANDATORY_SYSTEM_GESTURES: return 4; + case TAPPABLE_ELEMENT: + return 5; + case WINDOW_DECOR: + return 6; default: throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST," + " type=" + type); @@ -1076,7 +1184,8 @@ public final class WindowInsets { /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES }) + @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES, + MANDATORY_SYSTEM_GESTURES, TAPPABLE_ELEMENT}) public @interface InsetType { } @@ -1130,6 +1239,20 @@ public final class WindowInsets { return SYSTEM_GESTURES; } + /** + * @see #getMandatorySystemGestureInsets + */ + public static @InsetType int mandatorySystemGestures() { + return MANDATORY_SYSTEM_GESTURES; + } + + /** + * @see #getTappableElementInsets + */ + public static @InsetType int tappableElement() { + return TAPPABLE_ELEMENT; + } + /** * @return All system bars. Includes {@link #topBar()} as well as {@link #sideBars()}, but * not {@link #ime()}.