Loading api/current.txt +7 −3 Original line number Diff line number Diff line Loading @@ -54027,9 +54027,9 @@ package android.view { public final class WindowInsets { ctor public WindowInsets(android.view.WindowInsets); method @NonNull public android.view.WindowInsets consumeDisplayCutout(); method @NonNull public android.view.WindowInsets consumeStableInsets(); method @NonNull public android.view.WindowInsets consumeSystemWindowInsets(); method @Deprecated @NonNull public android.view.WindowInsets consumeDisplayCutout(); method @Deprecated @NonNull public android.view.WindowInsets consumeStableInsets(); method @Deprecated @NonNull public android.view.WindowInsets consumeSystemWindowInsets(); method @Nullable public android.view.DisplayCutout getDisplayCutout(); method @NonNull public android.graphics.Insets getInsets(int); method @NonNull public android.graphics.Insets getMandatorySystemGestureInsets(); Loading @@ -54055,6 +54055,7 @@ package android.view { method public boolean isVisible(int); method @Deprecated @NonNull public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int); method @Deprecated @NonNull public android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect); field @NonNull public static final android.view.WindowInsets CONSUMED; } public static final class WindowInsets.Builder { Loading Loading @@ -54086,10 +54087,13 @@ package android.view { } public interface WindowInsetsAnimationCallback { method public int getDispatchMode(); method public default void onFinish(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation); method public default void onPrepare(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation); method @NonNull public android.view.WindowInsets onProgress(@NonNull android.view.WindowInsets); method @NonNull public default android.view.WindowInsetsAnimationCallback.AnimationBounds onStart(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation, @NonNull android.view.WindowInsetsAnimationCallback.AnimationBounds); field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1 field public static final int DISPATCH_MODE_STOP = 0; // 0x0 } public static final class WindowInsetsAnimationCallback.AnimationBounds { core/java/android/view/View.java +14 −17 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LO import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP; import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.WindowInsetsAnimationCallback.DISPATCH_MODE_CONTINUE_ON_SUBTREE; import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; import static java.lang.Math.max; Loading Loading @@ -111,6 +112,7 @@ import android.view.AccessibilityIterators.WordTextSegmentIterator; import android.view.ContextMenu.ContextMenuInfo; import android.view.WindowInsetsAnimationCallback.AnimationBounds; import android.view.WindowInsetsAnimationCallback.InsetsAnimation; import android.view.WindowInsetsAnimationCallback.DispatchMode; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -949,22 +951,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static boolean sAcceptZeroSizeDragShadow; /** * Prior to Q, {@link #dispatchApplyWindowInsets} had some issues: * <ul> * <li>The modified insets changed by {@link #onApplyWindowInsets} were passed to the * Prior to R, {@link #dispatchApplyWindowInsets} had an issue: * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the * entire view hierarchy in prefix order, including siblings as well as siblings of parents * further down the hierarchy. This violates the basic concepts of the view hierarchy, and * thus, the hierarchical dispatching mechanism was hard to use for apps.</li> * * <li>Dispatch was stopped after the insets were fully consumed. This is somewhat confusing * for developers, but more importantly, by adding more granular information to * {@link WindowInsets} it becomes really cumbersome to define what consumed actually means * </li> * </ul> * * thus, the hierarchical dispatching mechanism was hard to use for apps. * <p> * In order to make window inset dispatching work properly, we dispatch window insets * in the view hierarchy in a proper hierarchical manner and don't stop dispatching if the * insets are consumed if this flag is set to {@code false}. * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}. */ static boolean sBrokenInsetsDispatch; Loading Loading @@ -5231,7 +5225,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P; sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL || targetSdkVersion < Build.VERSION_CODES.Q; || targetSdkVersion < Build.VERSION_CODES.R; sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q; Loading Loading @@ -11100,7 +11094,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Sets a {@link WindowInsetsAnimationCallback} to be notified about animations of windows that * cause insets. * * <p> * When setting a listener, it's {@link WindowInsetsAnimationCallback#getDispatchMode() dispatch * mode} will be retrieved and recorded until another listener will be set. * </p> * @param listener The listener to set. */ public void setWindowInsetsAnimationCallback(@Nullable WindowInsetsAnimationCallback listener) { core/java/android/view/ViewGroup.java +41 −8 Original line number Diff line number Diff line Loading @@ -17,11 +17,14 @@ package android.view; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; import static android.view.WindowInsetsAnimationCallback.DISPATCH_MODE_CONTINUE_ON_SUBTREE; import static android.view.WindowInsetsAnimationCallback.DISPATCH_MODE_STOP; import android.animation.LayoutTransition; import android.annotation.CallSuper; import android.annotation.IdRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.annotation.UiThread; import android.compat.annotation.UnsupportedAppUsage; Loading @@ -45,6 +48,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.os.SystemClock; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; import android.util.Pools; Loading @@ -52,6 +56,7 @@ import android.util.Pools.SynchronizedPool; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.view.WindowInsetsAnimationCallback.AnimationBounds; import android.view.WindowInsetsAnimationCallback.DispatchMode; import android.view.WindowInsetsAnimationCallback.InsetsAnimation; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -606,6 +611,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ int mChildUnhandledKeyListeners = 0; /** * Current dispatch mode of animation events * * @see WindowInsetsAnimationCallback#getDispatchMode() */ private @DispatchMode int mInsetsAnimationDispatchMode = DISPATCH_MODE_CONTINUE_ON_SUBTREE; /** * Empty ActionMode used as a sentinel in recursive entries to startActionModeForChild. * Loading Loading @@ -7170,6 +7182,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { insets = super.dispatchApplyWindowInsets(insets); if (insets.isConsumed()) { return insets; } if (View.sBrokenInsetsDispatch) { return brokenDispatchApplyWindowInsets(insets); } else { Loading @@ -7178,7 +7193,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } private WindowInsets brokenDispatchApplyWindowInsets(WindowInsets insets) { if (!insets.isConsumed()) { final int count = getChildCount(); for (int i = 0; i < count; i++) { insets = getChildAt(i).dispatchApplyWindowInsets(insets); Loading @@ -7186,7 +7200,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager break; } } } return insets; } Loading @@ -7198,10 +7211,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return insets; } @Override public void setWindowInsetsAnimationCallback(@Nullable WindowInsetsAnimationCallback listener) { super.setWindowInsetsAnimationCallback(listener); mInsetsAnimationDispatchMode = listener != null ? listener.getDispatchMode() : DISPATCH_MODE_CONTINUE_ON_SUBTREE; } @Override public void dispatchWindowInsetsAnimationPrepare( @NonNull InsetsAnimation animation) { super.dispatchWindowInsetsAnimationPrepare(animation); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationPrepare(animation); Loading @@ -7212,7 +7236,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @NonNull public AnimationBounds dispatchWindowInsetsAnimationStart( @NonNull InsetsAnimation animation, @NonNull AnimationBounds bounds) { super.dispatchWindowInsetsAnimationStart(animation, bounds); bounds = super.dispatchWindowInsetsAnimationStart(animation, bounds); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return bounds; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationStart(animation, bounds); Loading @@ -7224,6 +7251,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @NonNull public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets) { insets = super.dispatchWindowInsetsAnimationProgress(insets); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return insets; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationProgress(insets); Loading @@ -7234,6 +7264,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override public void dispatchWindowInsetsAnimationFinish(@NonNull InsetsAnimation animation) { super.dispatchWindowInsetsAnimationFinish(animation); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationFinish(animation); Loading core/java/android/view/WindowInsets.java +26 −6 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.Intent; import android.graphics.Insets; import android.graphics.Rect; import android.util.SparseArray; import android.view.View.OnApplyWindowInsetsListener; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.inputmethod.EditorInfo; Loading Loading @@ -96,13 +97,20 @@ public final class WindowInsets { private final boolean mCompatIgnoreVisibility; /** * Since new insets may be added in the future that existing apps couldn't * know about, this fully empty constant shouldn't be made available to apps * since it would allow them to inadvertently consume unknown insets by returning it. * @hide * A {@link WindowInsets} instance for which {@link #isConsumed()} returns {@code true}. * <p> * This can be used during insets dispatch in the view hierarchy by returning this value from * {@link View#onApplyWindowInsets(WindowInsets)} or * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets)} to stop dispatch * the insets to its children to avoid traversing the entire view hierarchy. * <p> * The application should return this instance once it has taken care of all insets on a certain * level in the view hierarchy, and doesn't need to dispatch to its children anymore for better * performance. * * @see #isConsumed() */ @UnsupportedAppUsage public static final WindowInsets CONSUMED; public static final @NonNull WindowInsets CONSUMED; static { CONSUMED = new WindowInsets((Rect) null, null, false, false, null); Loading Loading @@ -456,7 +464,11 @@ public final class WindowInsets { * Returns a copy of this WindowInsets with the cutout fully consumed. * * @return A modified copy of this WindowInsets * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED} * instead to stop dispatching insets. */ @Deprecated @NonNull public WindowInsets consumeDisplayCutout() { return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, Loading Loading @@ -504,7 +516,11 @@ public final class WindowInsets { * Returns a copy of this WindowInsets with the system window insets fully consumed. * * @return A modified copy of this WindowInsets * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED} * instead to stop dispatching insets. */ @Deprecated @NonNull public WindowInsets consumeSystemWindowInsets() { return new WindowInsets(null, null, Loading Loading @@ -754,7 +770,11 @@ public final class WindowInsets { * Returns a copy of this WindowInsets with the stable insets fully consumed. * * @return A modified copy of this WindowInsets * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED} * instead to stop dispatching insets. */ @Deprecated @NonNull public WindowInsets consumeStableInsets() { return consumeSystemWindowInsets(); Loading core/java/android/view/WindowInsetsAnimationCallback.java +57 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Insets; Loading @@ -24,12 +25,61 @@ import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; import android.view.animation.Interpolator; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Interface that allows the application to listen to animation events for windows that cause * insets. */ public interface WindowInsetsAnimationCallback { /** * Return value for {@link #getDispatchMode()}: Dispatching of animation events should * stop at this level in the view hierarchy, and no animation events should be dispatch to the * subtree of the view hierarchy. */ int DISPATCH_MODE_STOP = 0; /** * Return value for {@link #getDispatchMode()}: Dispatching of animation events should * continue in the view hierarchy. */ int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; /** @hide */ @IntDef(prefix = { "DISPATCH_MODE_" }, value = { DISPATCH_MODE_STOP, DISPATCH_MODE_CONTINUE_ON_SUBTREE }) @Retention(RetentionPolicy.SOURCE) @interface DispatchMode {} /** * Retrieves the dispatch mode of this listener. Dispatch of the all animation events is * hierarchical: It will starts at the root of the view hierarchy and then traverse it and * invoke the callback of the specific {@link View} that is being traversed. * The method may return either {@link #DISPATCH_MODE_CONTINUE_ON_SUBTREE} to indicate that * animation events should be propagated to the subtree of the view hierarchy, or * {@link #DISPATCH_MODE_STOP} to stop dispatching. In that case, all animation callbacks * related to the animation passed in will be stopped from propagating to the subtree of the * hierarchy. * <p> * Note that this method will only be invoked once when * {@link View#setWindowInsetsAnimationCallback setting the listener} and then the framework * will use the recorded result. * <p> * Also note that returning {@link #DISPATCH_MODE_STOP} here behaves the same way as returning * {@link WindowInsets#CONSUMED} during the regular insets dispatch in * {@link View#onApplyWindowInsets}. * * @return Either {@link #DISPATCH_MODE_CONTINUE_ON_SUBTREE} to indicate that dispatching of * animation events will continue to the subtree of the view hierarchy, or * {@link #DISPATCH_MODE_STOP} to indicate that animation events will stop dispatching. */ @DispatchMode int getDispatchMode(); /** * Called when an insets animation is about to start and before the views have been laid out in * the end state of the animation. The ordering of events during an insets animation is the Loading Loading @@ -75,10 +125,11 @@ public interface WindowInsetsAnimationCallback { * <p> * Note that, like {@link #onProgress}, dispatch of the animation start event is hierarchical: * It will starts at the root of the view hierarchy and then traverse it and invoke the callback * of the specific {@link View} that is being traversed. The method my return a modified * of the specific {@link View} that is being traversed. The method may return a modified * instance of the bounds by calling {@link AnimationBounds#inset} to indicate that a part of * the insets have been used to offset or clip its children, and the children shouldn't worry * about that part anymore. * about that part anymore. Furthermore, if {@link #getDispatchMode()} returns * {@link #DISPATCH_MODE_STOP}, children of this view will not receive the callback anymore. * * @param animation The animation that is about to start. * @param bounds The bounds in which animation happens. Loading @@ -102,7 +153,9 @@ public interface WindowInsetsAnimationCallback { * The method may return a modified instance by calling * {@link WindowInsets#inset(int, int, int, int)} to indicate that a part of the insets have * been used to offset or clip its children, and the children shouldn't worry about that part * anymore. * anymore. Furthermore, if {@link #getDispatchMode()} returns * {@link #DISPATCH_MODE_STOP}, children of this view will not receive the callback anymore. * * TODO: Introduce a way to map (type -> InsetAnimation) so app developer can query animation * for a given type e.g. callback.getAnimation(type) OR controller.getAnimation(type). * Or on the controller directly? Loading Loading @@ -237,6 +290,7 @@ public interface WindowInsetsAnimationCallback { * Class representing the range of an {@link InsetsAnimation} */ final class AnimationBounds { private final Insets mLowerBound; private final Insets mUpperBound; Loading Loading
api/current.txt +7 −3 Original line number Diff line number Diff line Loading @@ -54027,9 +54027,9 @@ package android.view { public final class WindowInsets { ctor public WindowInsets(android.view.WindowInsets); method @NonNull public android.view.WindowInsets consumeDisplayCutout(); method @NonNull public android.view.WindowInsets consumeStableInsets(); method @NonNull public android.view.WindowInsets consumeSystemWindowInsets(); method @Deprecated @NonNull public android.view.WindowInsets consumeDisplayCutout(); method @Deprecated @NonNull public android.view.WindowInsets consumeStableInsets(); method @Deprecated @NonNull public android.view.WindowInsets consumeSystemWindowInsets(); method @Nullable public android.view.DisplayCutout getDisplayCutout(); method @NonNull public android.graphics.Insets getInsets(int); method @NonNull public android.graphics.Insets getMandatorySystemGestureInsets(); Loading @@ -54055,6 +54055,7 @@ package android.view { method public boolean isVisible(int); method @Deprecated @NonNull public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int); method @Deprecated @NonNull public android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect); field @NonNull public static final android.view.WindowInsets CONSUMED; } public static final class WindowInsets.Builder { Loading Loading @@ -54086,10 +54087,13 @@ package android.view { } public interface WindowInsetsAnimationCallback { method public int getDispatchMode(); method public default void onFinish(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation); method public default void onPrepare(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation); method @NonNull public android.view.WindowInsets onProgress(@NonNull android.view.WindowInsets); method @NonNull public default android.view.WindowInsetsAnimationCallback.AnimationBounds onStart(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation, @NonNull android.view.WindowInsetsAnimationCallback.AnimationBounds); field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1 field public static final int DISPATCH_MODE_STOP = 0; // 0x0 } public static final class WindowInsetsAnimationCallback.AnimationBounds {
core/java/android/view/View.java +14 −17 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LO import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP; import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.WindowInsetsAnimationCallback.DISPATCH_MODE_CONTINUE_ON_SUBTREE; import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; import static java.lang.Math.max; Loading Loading @@ -111,6 +112,7 @@ import android.view.AccessibilityIterators.WordTextSegmentIterator; import android.view.ContextMenu.ContextMenuInfo; import android.view.WindowInsetsAnimationCallback.AnimationBounds; import android.view.WindowInsetsAnimationCallback.InsetsAnimation; import android.view.WindowInsetsAnimationCallback.DispatchMode; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -949,22 +951,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static boolean sAcceptZeroSizeDragShadow; /** * Prior to Q, {@link #dispatchApplyWindowInsets} had some issues: * <ul> * <li>The modified insets changed by {@link #onApplyWindowInsets} were passed to the * Prior to R, {@link #dispatchApplyWindowInsets} had an issue: * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the * entire view hierarchy in prefix order, including siblings as well as siblings of parents * further down the hierarchy. This violates the basic concepts of the view hierarchy, and * thus, the hierarchical dispatching mechanism was hard to use for apps.</li> * * <li>Dispatch was stopped after the insets were fully consumed. This is somewhat confusing * for developers, but more importantly, by adding more granular information to * {@link WindowInsets} it becomes really cumbersome to define what consumed actually means * </li> * </ul> * * thus, the hierarchical dispatching mechanism was hard to use for apps. * <p> * In order to make window inset dispatching work properly, we dispatch window insets * in the view hierarchy in a proper hierarchical manner and don't stop dispatching if the * insets are consumed if this flag is set to {@code false}. * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}. */ static boolean sBrokenInsetsDispatch; Loading Loading @@ -5231,7 +5225,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P; sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL || targetSdkVersion < Build.VERSION_CODES.Q; || targetSdkVersion < Build.VERSION_CODES.R; sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q; Loading Loading @@ -11100,7 +11094,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Sets a {@link WindowInsetsAnimationCallback} to be notified about animations of windows that * cause insets. * * <p> * When setting a listener, it's {@link WindowInsetsAnimationCallback#getDispatchMode() dispatch * mode} will be retrieved and recorded until another listener will be set. * </p> * @param listener The listener to set. */ public void setWindowInsetsAnimationCallback(@Nullable WindowInsetsAnimationCallback listener) {
core/java/android/view/ViewGroup.java +41 −8 Original line number Diff line number Diff line Loading @@ -17,11 +17,14 @@ package android.view; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; import static android.view.WindowInsetsAnimationCallback.DISPATCH_MODE_CONTINUE_ON_SUBTREE; import static android.view.WindowInsetsAnimationCallback.DISPATCH_MODE_STOP; import android.animation.LayoutTransition; import android.annotation.CallSuper; import android.annotation.IdRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.annotation.UiThread; import android.compat.annotation.UnsupportedAppUsage; Loading @@ -45,6 +48,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.os.SystemClock; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; import android.util.Pools; Loading @@ -52,6 +56,7 @@ import android.util.Pools.SynchronizedPool; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.view.WindowInsetsAnimationCallback.AnimationBounds; import android.view.WindowInsetsAnimationCallback.DispatchMode; import android.view.WindowInsetsAnimationCallback.InsetsAnimation; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -606,6 +611,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ int mChildUnhandledKeyListeners = 0; /** * Current dispatch mode of animation events * * @see WindowInsetsAnimationCallback#getDispatchMode() */ private @DispatchMode int mInsetsAnimationDispatchMode = DISPATCH_MODE_CONTINUE_ON_SUBTREE; /** * Empty ActionMode used as a sentinel in recursive entries to startActionModeForChild. * Loading Loading @@ -7170,6 +7182,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { insets = super.dispatchApplyWindowInsets(insets); if (insets.isConsumed()) { return insets; } if (View.sBrokenInsetsDispatch) { return brokenDispatchApplyWindowInsets(insets); } else { Loading @@ -7178,7 +7193,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } private WindowInsets brokenDispatchApplyWindowInsets(WindowInsets insets) { if (!insets.isConsumed()) { final int count = getChildCount(); for (int i = 0; i < count; i++) { insets = getChildAt(i).dispatchApplyWindowInsets(insets); Loading @@ -7186,7 +7200,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager break; } } } return insets; } Loading @@ -7198,10 +7211,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return insets; } @Override public void setWindowInsetsAnimationCallback(@Nullable WindowInsetsAnimationCallback listener) { super.setWindowInsetsAnimationCallback(listener); mInsetsAnimationDispatchMode = listener != null ? listener.getDispatchMode() : DISPATCH_MODE_CONTINUE_ON_SUBTREE; } @Override public void dispatchWindowInsetsAnimationPrepare( @NonNull InsetsAnimation animation) { super.dispatchWindowInsetsAnimationPrepare(animation); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationPrepare(animation); Loading @@ -7212,7 +7236,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @NonNull public AnimationBounds dispatchWindowInsetsAnimationStart( @NonNull InsetsAnimation animation, @NonNull AnimationBounds bounds) { super.dispatchWindowInsetsAnimationStart(animation, bounds); bounds = super.dispatchWindowInsetsAnimationStart(animation, bounds); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return bounds; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationStart(animation, bounds); Loading @@ -7224,6 +7251,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @NonNull public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets) { insets = super.dispatchWindowInsetsAnimationProgress(insets); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return insets; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationProgress(insets); Loading @@ -7234,6 +7264,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override public void dispatchWindowInsetsAnimationFinish(@NonNull InsetsAnimation animation) { super.dispatchWindowInsetsAnimationFinish(animation); if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return; } final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).dispatchWindowInsetsAnimationFinish(animation); Loading
core/java/android/view/WindowInsets.java +26 −6 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.Intent; import android.graphics.Insets; import android.graphics.Rect; import android.util.SparseArray; import android.view.View.OnApplyWindowInsetsListener; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.inputmethod.EditorInfo; Loading Loading @@ -96,13 +97,20 @@ public final class WindowInsets { private final boolean mCompatIgnoreVisibility; /** * Since new insets may be added in the future that existing apps couldn't * know about, this fully empty constant shouldn't be made available to apps * since it would allow them to inadvertently consume unknown insets by returning it. * @hide * A {@link WindowInsets} instance for which {@link #isConsumed()} returns {@code true}. * <p> * This can be used during insets dispatch in the view hierarchy by returning this value from * {@link View#onApplyWindowInsets(WindowInsets)} or * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets)} to stop dispatch * the insets to its children to avoid traversing the entire view hierarchy. * <p> * The application should return this instance once it has taken care of all insets on a certain * level in the view hierarchy, and doesn't need to dispatch to its children anymore for better * performance. * * @see #isConsumed() */ @UnsupportedAppUsage public static final WindowInsets CONSUMED; public static final @NonNull WindowInsets CONSUMED; static { CONSUMED = new WindowInsets((Rect) null, null, false, false, null); Loading Loading @@ -456,7 +464,11 @@ public final class WindowInsets { * Returns a copy of this WindowInsets with the cutout fully consumed. * * @return A modified copy of this WindowInsets * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED} * instead to stop dispatching insets. */ @Deprecated @NonNull public WindowInsets consumeDisplayCutout() { return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, Loading Loading @@ -504,7 +516,11 @@ public final class WindowInsets { * Returns a copy of this WindowInsets with the system window insets fully consumed. * * @return A modified copy of this WindowInsets * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED} * instead to stop dispatching insets. */ @Deprecated @NonNull public WindowInsets consumeSystemWindowInsets() { return new WindowInsets(null, null, Loading Loading @@ -754,7 +770,11 @@ public final class WindowInsets { * Returns a copy of this WindowInsets with the stable insets fully consumed. * * @return A modified copy of this WindowInsets * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED} * instead to stop dispatching insets. */ @Deprecated @NonNull public WindowInsets consumeStableInsets() { return consumeSystemWindowInsets(); Loading
core/java/android/view/WindowInsetsAnimationCallback.java +57 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Insets; Loading @@ -24,12 +25,61 @@ import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; import android.view.animation.Interpolator; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Interface that allows the application to listen to animation events for windows that cause * insets. */ public interface WindowInsetsAnimationCallback { /** * Return value for {@link #getDispatchMode()}: Dispatching of animation events should * stop at this level in the view hierarchy, and no animation events should be dispatch to the * subtree of the view hierarchy. */ int DISPATCH_MODE_STOP = 0; /** * Return value for {@link #getDispatchMode()}: Dispatching of animation events should * continue in the view hierarchy. */ int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; /** @hide */ @IntDef(prefix = { "DISPATCH_MODE_" }, value = { DISPATCH_MODE_STOP, DISPATCH_MODE_CONTINUE_ON_SUBTREE }) @Retention(RetentionPolicy.SOURCE) @interface DispatchMode {} /** * Retrieves the dispatch mode of this listener. Dispatch of the all animation events is * hierarchical: It will starts at the root of the view hierarchy and then traverse it and * invoke the callback of the specific {@link View} that is being traversed. * The method may return either {@link #DISPATCH_MODE_CONTINUE_ON_SUBTREE} to indicate that * animation events should be propagated to the subtree of the view hierarchy, or * {@link #DISPATCH_MODE_STOP} to stop dispatching. In that case, all animation callbacks * related to the animation passed in will be stopped from propagating to the subtree of the * hierarchy. * <p> * Note that this method will only be invoked once when * {@link View#setWindowInsetsAnimationCallback setting the listener} and then the framework * will use the recorded result. * <p> * Also note that returning {@link #DISPATCH_MODE_STOP} here behaves the same way as returning * {@link WindowInsets#CONSUMED} during the regular insets dispatch in * {@link View#onApplyWindowInsets}. * * @return Either {@link #DISPATCH_MODE_CONTINUE_ON_SUBTREE} to indicate that dispatching of * animation events will continue to the subtree of the view hierarchy, or * {@link #DISPATCH_MODE_STOP} to indicate that animation events will stop dispatching. */ @DispatchMode int getDispatchMode(); /** * Called when an insets animation is about to start and before the views have been laid out in * the end state of the animation. The ordering of events during an insets animation is the Loading Loading @@ -75,10 +125,11 @@ public interface WindowInsetsAnimationCallback { * <p> * Note that, like {@link #onProgress}, dispatch of the animation start event is hierarchical: * It will starts at the root of the view hierarchy and then traverse it and invoke the callback * of the specific {@link View} that is being traversed. The method my return a modified * of the specific {@link View} that is being traversed. The method may return a modified * instance of the bounds by calling {@link AnimationBounds#inset} to indicate that a part of * the insets have been used to offset or clip its children, and the children shouldn't worry * about that part anymore. * about that part anymore. Furthermore, if {@link #getDispatchMode()} returns * {@link #DISPATCH_MODE_STOP}, children of this view will not receive the callback anymore. * * @param animation The animation that is about to start. * @param bounds The bounds in which animation happens. Loading @@ -102,7 +153,9 @@ public interface WindowInsetsAnimationCallback { * The method may return a modified instance by calling * {@link WindowInsets#inset(int, int, int, int)} to indicate that a part of the insets have * been used to offset or clip its children, and the children shouldn't worry about that part * anymore. * anymore. Furthermore, if {@link #getDispatchMode()} returns * {@link #DISPATCH_MODE_STOP}, children of this view will not receive the callback anymore. * * TODO: Introduce a way to map (type -> InsetAnimation) so app developer can query animation * for a given type e.g. callback.getAnimation(type) OR controller.getAnimation(type). * Or on the controller directly? Loading Loading @@ -237,6 +290,7 @@ public interface WindowInsetsAnimationCallback { * Class representing the range of an {@link InsetsAnimation} */ final class AnimationBounds { private final Insets mLowerBound; private final Insets mUpperBound; Loading