summaryrefslogtreecommitdiff
path: root/core/java/android/view/WindowInsets.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/view/WindowInsets.java')
-rw-r--r--core/java/android/view/WindowInsets.java117
1 files changed, 114 insertions, 3 deletions
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index e5cbe96b9173..fbd8141ae27a 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -20,6 +20,10 @@ package android.view;
import android.annotation.Nullable;
import android.graphics.Rect;
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
/**
* Describes a set of insets for window content.
*
@@ -27,6 +31,12 @@ import android.graphics.Rect;
* To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance
* with the adjusted properties.</p>
*
+ * <p>Note: Before {@link android.os.Build.VERSION_CODES#P P}, WindowInsets instances were only
+ * immutable during a single layout pass (i.e. would return the same values between
+ * {@link View#onApplyWindowInsets} and {@link View#onLayout}, but could return other values
+ * otherwise). Starting with {@link android.os.Build.VERSION_CODES#P P}, WindowInsets are
+ * always immutable and implement equality.
+ *
* @see View.OnApplyWindowInsetsListener
* @see View#onApplyWindowInsets(WindowInsets)
*/
@@ -69,13 +79,14 @@ public final class WindowInsets {
public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
mSystemWindowInsetsConsumed = systemWindowInsets == null;
- mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets;
+ mSystemWindowInsets = mSystemWindowInsetsConsumed
+ ? EMPTY_RECT : new Rect(systemWindowInsets);
mWindowDecorInsetsConsumed = windowDecorInsets == null;
- mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : windowDecorInsets;
+ mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : new Rect(windowDecorInsets);
mStableInsetsConsumed = stableInsets == null;
- mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : stableInsets;
+ mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : new Rect(stableInsets);
mIsRound = isRound;
mAlwaysConsumeNavBar = alwaysConsumeNavBar;
@@ -535,4 +546,104 @@ public final class WindowInsets {
+ (isRound() ? " round" : "")
+ "}";
}
+
+ /**
+ * Returns a copy of this instance inset in the given directions.
+ *
+ * @see #inset(int, int, int, int)
+ * @hide
+ */
+ public WindowInsets inset(Rect r) {
+ return inset(r.left, r.top, r.right, r.bottom);
+ }
+
+ /**
+ * Returns a copy of this instance inset in the given directions.
+ *
+ * This is intended for dispatching insets to areas of the window that are smaller than the
+ * current area.
+ *
+ * <p>Example:
+ * <pre>
+ * childView.dispatchApplyWindowInsets(insets.inset(
+ * childMarginLeft, childMarginTop, childMarginBottom, childMarginRight));
+ * </pre>
+ *
+ * @param left the amount of insets to remove from the left. Must be non-negative.
+ * @param top the amount of insets to remove from the top. Must be non-negative.
+ * @param right the amount of insets to remove from the right. Must be non-negative.
+ * @param bottom the amount of insets to remove from the bottom. Must be non-negative.
+ *
+ * @return the inset insets
+ *
+ * @hide pending API
+ */
+ public WindowInsets inset(int left, int top, int right, int bottom) {
+ Preconditions.checkArgumentNonnegative(left);
+ Preconditions.checkArgumentNonnegative(top);
+ Preconditions.checkArgumentNonnegative(right);
+ Preconditions.checkArgumentNonnegative(bottom);
+
+ WindowInsets result = new WindowInsets(this);
+ if (!result.mSystemWindowInsetsConsumed) {
+ result.mSystemWindowInsets =
+ insetInsets(result.mSystemWindowInsets, left, top, right, bottom);
+ }
+ if (!result.mWindowDecorInsetsConsumed) {
+ result.mWindowDecorInsets =
+ insetInsets(result.mWindowDecorInsets, left, top, right, bottom);
+ }
+ if (!result.mStableInsetsConsumed) {
+ result.mStableInsets = insetInsets(result.mStableInsets, left, top, right, bottom);
+ }
+ if (mDisplayCutout != null) {
+ result.mDisplayCutout = result.mDisplayCutout.inset(left, top, right, bottom);
+ if (result.mDisplayCutout.isEmpty()) {
+ result.mDisplayCutout = null;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || !(o instanceof WindowInsets)) return false;
+ WindowInsets that = (WindowInsets) o;
+ return mIsRound == that.mIsRound
+ && mAlwaysConsumeNavBar == that.mAlwaysConsumeNavBar
+ && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed
+ && mWindowDecorInsetsConsumed == that.mWindowDecorInsetsConsumed
+ && mStableInsetsConsumed == that.mStableInsetsConsumed
+ && mDisplayCutoutConsumed == that.mDisplayCutoutConsumed
+ && Objects.equals(mSystemWindowInsets, that.mSystemWindowInsets)
+ && Objects.equals(mWindowDecorInsets, that.mWindowDecorInsets)
+ && Objects.equals(mStableInsets, that.mStableInsets)
+ && Objects.equals(mDisplayCutout, that.mDisplayCutout);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSystemWindowInsets, mWindowDecorInsets, mStableInsets, mIsRound,
+ mDisplayCutout, mAlwaysConsumeNavBar, mSystemWindowInsetsConsumed,
+ mWindowDecorInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed);
+ }
+
+ private static Rect insetInsets(Rect insets, int left, int top, int right, int bottom) {
+ int newLeft = Math.max(0, insets.left - left);
+ int newTop = Math.max(0, insets.top - top);
+ int newRight = Math.max(0, insets.right - right);
+ int newBottom = Math.max(0, insets.bottom - bottom);
+ if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
+ return insets;
+ }
+ return new Rect(newLeft, newTop, newRight, newBottom);
+ }
+
+ /**
+ * @return whether system window insets have been consumed.
+ */
+ boolean isSystemWindowInsetsConsumed() {
+ return mSystemWindowInsetsConsumed;
+ }
}