diff options
| -rw-r--r-- | api/current.txt | 10 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 17 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/Window.java | 48 | ||||
| -rw-r--r-- | core/java/android/view/WindowInsetsAnimationCallback.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/WindowInsetsAnimationControlListener.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/WindowInsetsAnimationController.java | 3 | ||||
| -rw-r--r-- | core/java/android/view/WindowInsetsController.java | 56 | ||||
| -rw-r--r-- | core/java/android/view/WindowManager.java | 6 | ||||
| -rw-r--r-- | core/java/com/android/internal/policy/PhoneWindow.java | 24 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/InsetsControllerTest.java | 6 |
11 files changed, 67 insertions, 129 deletions
diff --git a/api/current.txt b/api/current.txt index 1306bfa7fb05..d5a0ba4c6262 100644 --- a/api/current.txt +++ b/api/current.txt @@ -54811,7 +54811,6 @@ package android.view { method public final void removeOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener); method public boolean requestFeature(int); method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int); - method public void resetOnContentApplyWindowInsetsListener(); method public abstract void restoreHierarchyState(android.os.Bundle); method public abstract android.os.Bundle saveHierarchyState(); method public void setAllowEnterTransitionOverlap(boolean); @@ -54829,6 +54828,7 @@ package android.view { method public abstract void setContentView(android.view.View); method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams); method public abstract void setDecorCaptionShade(int); + method public void setDecorFitsSystemWindows(boolean); method protected void setDefaultWindowFormat(int); method public void setDimAmount(float); method public void setElevation(float); @@ -54850,7 +54850,6 @@ package android.view { method public abstract void setNavigationBarColor(@ColorInt int); method public void setNavigationBarContrastEnforced(boolean); method public void setNavigationBarDividerColor(@ColorInt int); - method public void setOnContentApplyWindowInsetsListener(@Nullable android.view.Window.OnContentApplyWindowInsetsListener); method public void setPreferMinimalPostProcessing(boolean); method public void setReenterTransition(android.transition.Transition); method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable); @@ -54945,10 +54944,6 @@ package android.view { method @Nullable public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int); } - public static interface Window.OnContentApplyWindowInsetsListener { - method @NonNull public android.util.Pair<android.graphics.Insets,android.view.WindowInsets> onContentApplyWindowInsets(@NonNull android.view.WindowInsets); - } - public static interface Window.OnFrameMetricsAvailableListener { method public void onFrameMetricsAvailable(android.view.Window, android.view.FrameMetrics, int); } @@ -55099,16 +55094,13 @@ package android.view { } public interface WindowInsetsController { - method public default void controlInputMethodAnimation(long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener); method public void controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener); method public int getSystemBarsAppearance(); method public int getSystemBarsBehavior(); method public void hide(int); - method public default void hideInputMethod(); method public void setSystemBarsAppearance(int, int); method public void setSystemBarsBehavior(int); method public void show(int); - method public default void showInputMethod(); field public static final int APPEARANCE_LIGHT_NAVIGATION_BARS = 16; // 0x10 field public static final int APPEARANCE_LIGHT_STATUS_BARS = 8; // 0x8 field public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1 diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d70bf22fcfbf..ee7f6fb11de6 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3654,8 +3654,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call - * {@link Window#setOnContentApplyWindowInsetsListener} with {@code null} or a listener that - * doesn't fit the navigation bar on the window content level. + * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}. */ public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; @@ -3683,8 +3682,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call - * {@link Window#setOnContentApplyWindowInsetsListener} with {@code null} or a listener that - * doesn't fit the status bar on the window content level. + * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}. */ @Deprecated public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; @@ -4673,7 +4671,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners; - private WindowInsetsAnimationCallback mWindowInsetsAnimationCallback; + WindowInsetsAnimationCallback mWindowInsetsAnimationCallback; /** * This lives here since it's only valid for interactive views. @@ -11537,7 +11535,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * @see #PFLAG4_OPTIONAL_FITS_SYSTEM_WINDOWS + * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS * @hide */ public void makeFrameworkOptionalFitsSystemWindows() { @@ -11545,6 +11543,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * @hide + */ + public boolean isFrameworkOptionalFitsSystemWindows() { + return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0; + } + + /** * Returns the visibility status for this view. * * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 4f03ca152850..d416d420feda 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -7239,6 +7239,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public void dispatchWindowInsetsAnimationPrepare( @NonNull InsetsAnimation animation) { super.dispatchWindowInsetsAnimationPrepare(animation); + + // If we are root-level content view that fits insets, set dispatch mode to stop to imitate + // consume behavior. + boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0 + || isFrameworkOptionalFitsSystemWindows(); + if (isOptionalFitSystemWindows && mAttachInfo != null + && getListenerInfo().mWindowInsetsAnimationCallback == null + && mAttachInfo.mContentOnApplyWindowInsetsListener != null) { + mInsetsAnimationDispatchMode = DISPATCH_MODE_STOP; + return; + } + if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) { return; } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 0ef4e338f81c..4b284dbf9ed4 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -697,12 +697,10 @@ public abstract class Window { } /** - * Listener for applying window insets on the content of a window in a custom way. + * Listener for applying window insets on the content of a window. Used only by the framework to + * fit content according to legacy SystemUI flags. * - * <p>Apps may choose to implement this interface if they want to apply custom policy - * to the way that window insets are treated for fitting root-level content views. - * - * @see Window#setOnContentApplyWindowInsetsListener(OnContentApplyWindowInsetsListener) + * @hide */ public interface OnContentApplyWindowInsetsListener { @@ -716,13 +714,15 @@ public abstract class Window { * * @param insets The root level insets that are about to be dispatched * @return A pair, with the first element containing the insets to apply as margin to the - * root-level content views, and the second element determining what should be - * dispatched to the content view. + * root-level content views, and the second element determining what should be + * dispatched to the content view. */ - @NonNull Pair<Insets, WindowInsets> onContentApplyWindowInsets( + @NonNull + Pair<Insets, WindowInsets> onContentApplyWindowInsets( @NonNull WindowInsets insets); } + public Window(Context context) { mContext = context; mFeatures = mLocalFeatures = getDefaultFeatures(context); @@ -1311,33 +1311,21 @@ public abstract class Window { } /** - * Sets the listener to be invoked when fitting root-level content views. + * Sets whether the decor view should fit root-level content views for {@link WindowInsets}. * <p> - * By default, a listener that inspects the now deprecated {@link View#SYSTEM_UI_LAYOUT_FLAGS} - * as well the {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag is installed and - * fits content according to these flags. + * If set to {@code true}, the framework will inspect the now deprecated + * {@link View#SYSTEM_UI_LAYOUT_FLAGS} as well the + * {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag and fits content according + * to these flags. * </p> - * @param contentOnApplyWindowInsetsListener The listener to use for fitting root-level content - * views, or {@code null} to disable any kind of - * content fitting on the window level and letting the - * {@link WindowInsets} pass through to the content - * view. - * @see OnContentApplyWindowInsetsListener - */ - public void setOnContentApplyWindowInsetsListener( - @Nullable OnContentApplyWindowInsetsListener contentOnApplyWindowInsetsListener) { - } - - /** - * Resets the listener set via {@link #setOnContentApplyWindowInsetsListener} to the default - * state. * <p> - * By default, a listener that inspects the now deprecated {@link View#SYSTEM_UI_LAYOUT_FLAGS} - * as well the {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag is installed and - * fits content according to these flags. + * If set to {@code false}, the framework will not fit the content view to the insets and will + * just pass through the {@link WindowInsets} to the content view. * </p> + * @param decorFitsSystemWindows Whether the decor view should fit root-level content views for + * insets. */ - public void resetOnContentApplyWindowInsetsListener() { + public void setDecorFitsSystemWindows(boolean decorFitsSystemWindows) { } /** diff --git a/core/java/android/view/WindowInsetsAnimationCallback.java b/core/java/android/view/WindowInsetsAnimationCallback.java index 1e04d02fcb80..4c8463b37df4 100644 --- a/core/java/android/view/WindowInsetsAnimationCallback.java +++ b/core/java/android/view/WindowInsetsAnimationCallback.java @@ -86,9 +86,9 @@ public interface WindowInsetsAnimationCallback { * following: * <p> * <ul> - * <li>Application calls {@link WindowInsetsController#hideInputMethod()}, - * {@link WindowInsetsController#showInputMethod()}, - * {@link WindowInsetsController#controlInputMethodAnimation}</li> + * <li>Application calls {@link WindowInsetsController#hide(int)}, + * {@link WindowInsetsController#show(int)}, + * {@link WindowInsetsController#controlWindowInsetsAnimation}</li> * <li>onPrepare is called on the view hierarchy listeners</li> * <li>{@link View#onApplyWindowInsets} will be called with the end state of the * animation</li> @@ -106,12 +106,12 @@ public interface WindowInsetsAnimationCallback { * related methods. * <p> * Note: If the animation is application controlled by using - * {@link WindowInsetsController#controlInputMethodAnimation}, the end state of the animation + * {@link WindowInsetsController#controlWindowInsetsAnimation}, the end state of the animation * is undefined as the application may decide on the end state only by passing in the * {@code shown} parameter when calling {@link WindowInsetsAnimationController#finish}. In this * situation, the system will dispatch the insets in the opposite visibility state before the * animation starts. Example: When controlling the input method with - * {@link WindowInsetsController#controlInputMethodAnimation} and the input method is currently + * {@link WindowInsetsController#controlWindowInsetsAnimation} and the input method is currently * showing, {@link View#onApplyWindowInsets} will receive a {@link WindowInsets} instance for * which {@link WindowInsets#isVisible} will return {@code false} for {@link Type#ime}. * @@ -246,7 +246,7 @@ public interface WindowInsetsAnimationCallback { * be the same as the application passed into * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}, * interpolated with the interpolator passed into - * {@link WindowInsetsController#controlInputMethodAnimation}. + * {@link WindowInsetsController#controlWindowInsetsAnimation}. * </p> * <p> * Note: For system-initiated animations, this will always return a valid value between 0 diff --git a/core/java/android/view/WindowInsetsAnimationControlListener.java b/core/java/android/view/WindowInsetsAnimationControlListener.java index f91254de33ff..701bd3158b1e 100644 --- a/core/java/android/view/WindowInsetsAnimationControlListener.java +++ b/core/java/android/view/WindowInsetsAnimationControlListener.java @@ -39,7 +39,7 @@ public interface WindowInsetsAnimationControlListener { * @param controller The controller to control the inset animation. * @param types The {@link InsetsType}s it was able to gain control over. Note that this may be * different than the types passed into - * {@link WindowInsetsController#controlInputMethodAnimation} in case the window + * {@link WindowInsetsController#controlWindowInsetsAnimation} in case the window * wasn't able to gain the controls because it wasn't the IME target or not * currently the window that's controlling the system bars. */ diff --git a/core/java/android/view/WindowInsetsAnimationController.java b/core/java/android/view/WindowInsetsAnimationController.java index 2bf0d277268d..4a864be64f64 100644 --- a/core/java/android/view/WindowInsetsAnimationController.java +++ b/core/java/android/view/WindowInsetsAnimationController.java @@ -23,6 +23,7 @@ import android.annotation.SuppressLint; import android.graphics.Insets; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsAnimationCallback.AnimationBounds; +import android.view.animation.Interpolator; /** * Controller for app-driven animation of system windows. @@ -32,7 +33,7 @@ import android.view.WindowInsetsAnimationCallback.AnimationBounds; * synchronized, such that changes the system windows and the app's current frame * are rendered at the same time. * <p> - * Control is obtained through {@link WindowInsetsController#controlInputMethodAnimation}. + * Control is obtained through {@link WindowInsetsController#controlWindowInsetsAnimation}. */ @SuppressLint("NotClosable") public interface WindowInsetsAnimationController { diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java index 02323cfb4f00..f501de91b3b7 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -167,62 +167,6 @@ public interface WindowInsetsController { @NonNull WindowInsetsAnimationControlListener listener); /** - * Lets the application control the animation for showing the IME in a frame-by-frame manner by - * modifying the position of the IME when it's causing insets. - * - * @param durationMillis Duration of the animation in - * {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or -1 if the - * animation doesn't have a predetermined duration. This value will be - * passed to {@link InsetsAnimation#getDurationMillis()} - * @param interpolator The interpolator used for this animation, or {@code null} if this - * animation doesn't follow an interpolation curve. This value will be - * passed to {@link InsetsAnimation#getInterpolator()} and used to calculate - * {@link InsetsAnimation#getInterpolatedFraction()}. - * @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the - * IME are ready to be controlled, among other callbacks. - * - * @see InsetsAnimation#getFraction() - * @see InsetsAnimation#getInterpolatedFraction() - * @see InsetsAnimation#getInterpolator() - * @see InsetsAnimation#getDurationMillis() - */ - default void controlInputMethodAnimation(long durationMillis, - @Nullable Interpolator interpolator, - @NonNull WindowInsetsAnimationControlListener listener) { - controlWindowInsetsAnimation(ime(), durationMillis, interpolator, listener); - } - - /** - * Makes the IME appear on screen. - * <p> - * Note that if the window currently doesn't have control over the IME, because it doesn't have - * focus, it will apply the change as soon as the window gains control. The app can listen to - * the event by observing {@link View#onApplyWindowInsets} and checking visibility with - * {@link WindowInsets#isVisible}. - * - * @see #controlInputMethodAnimation - * @see #hideInputMethod() - */ - default void showInputMethod() { - show(ime()); - } - - /** - * Makes the IME disappear on screen. - * <p> - * Note that if the window currently doesn't have control over IME, because it doesn't have - * focus, it will apply the change as soon as the window gains control. The app can listen to - * the event by observing {@link View#onApplyWindowInsets} and checking visibility with - * {@link WindowInsets#isVisible}. - * - * @see #controlInputMethodAnimation - * @see #showInputMethod() - */ - default void hideInputMethod() { - hide(ime()); - } - - /** * Controls the appearance of system bars. * <p> * For example, the following statement adds {@link #APPEARANCE_LIGHT_STATUS_BARS}: diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index a6450a10561b..dad767142ba1 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -80,6 +80,7 @@ import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; import android.util.proto.ProtoOutputStream; +import android.view.View.OnApplyWindowInsetsListener; import android.view.WindowInsets.Side; import android.view.WindowInsets.Side.InsetsSide; import android.view.WindowInsets.Type; @@ -2193,8 +2194,9 @@ public interface WindowManager extends ViewManager { * value for {@link #softInputMode} will be ignored; the window will * not resize, but will stay fullscreen. * - * @deprecated Use {@link Window#setOnContentApplyWindowInsetsListener} instead with a - * listener that fits {@link Type#ime()} instead. + * @deprecated Call {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false} and + * install an {@link OnApplyWindowInsetsListener} on your root content view that fits insets + * of type {@link Type#ime()}. */ @Deprecated public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10; diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index f13a638f7844..5e69a5ffd035 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -320,7 +320,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { /** @see ViewRootImpl#mActivityConfigCallback */ private ActivityConfigCallback mActivityConfigCallback; - private OnContentApplyWindowInsetsListener mPendingOnContentApplyWindowInsetsListener; + private OnContentApplyWindowInsetsListener mPendingOnContentApplyWindowInsetsListener + = createDefaultContentWindowInsetsListener(); static class WindowManagerHolder { static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface( @@ -2109,14 +2110,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { /** Notify when decor view is attached to window and {@link ViewRootImpl} is available. */ void onViewRootImplSet(ViewRootImpl viewRoot) { viewRoot.setActivityConfigCallback(mActivityConfigCallback); - if (mPendingOnContentApplyWindowInsetsListener != null) { - viewRoot.setOnContentApplyWindowInsetsListener( - mPendingOnContentApplyWindowInsetsListener); - mPendingOnContentApplyWindowInsetsListener = null; - } else { - viewRoot.setOnContentApplyWindowInsetsListener( - createDefaultContentWindowInsetsListener()); - } + viewRoot.setOnContentApplyWindowInsetsListener( + mPendingOnContentApplyWindowInsetsListener); + mPendingOnContentApplyWindowInsetsListener = null; } private OnContentApplyWindowInsetsListener createDefaultContentWindowInsetsListener() { @@ -3902,17 +3898,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override - public void setOnContentApplyWindowInsetsListener(OnContentApplyWindowInsetsListener listener) { + public void setDecorFitsSystemWindows(boolean decorFitsSystemWindows) { ViewRootImpl impl = getViewRootImpl(); + OnContentApplyWindowInsetsListener listener = decorFitsSystemWindows + ? createDefaultContentWindowInsetsListener() + : null; if (impl != null) { impl.setOnContentApplyWindowInsetsListener(listener); } else { mPendingOnContentApplyWindowInsetsListener = listener; } } - - @Override - public void resetOnContentApplyWindowInsetsListener() { - setOnContentApplyWindowInsetsListener(createDefaultContentWindowInsetsListener()); - } } diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index e68c4b8d2ab3..576e04ff62ca 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -432,7 +432,7 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -456,7 +456,7 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -476,7 +476,7 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); |