WindowInsetsAnimation: Clean up API
Fixes issues the app developers have raised with the WindowInsetsAnimation API: - it really makes more sense to have the Animation as the outer class, and the Callback nested within - it was not obvious previously that multiple animations could be running at the same time. A new argument to onProgress now makes this abundantly clear by passing in the list of running animations. - The dispatch mode really fits better as a final property on the callback, rather than it being queried once from a getter. Also fixes lint warnings. Fixes: 143556682 Test: make checkapi; atest WindowInsetsControllerTests Change-Id: I8cd8faac70dd5a15d779d2c983f0a0ea5d6bbd8e
This commit is contained in:
@@ -53541,10 +53541,10 @@ package android.view {
|
||||
method public boolean dispatchUnhandledMove(android.view.View, int);
|
||||
method protected void dispatchVisibilityChanged(@NonNull android.view.View, int);
|
||||
method public void dispatchWindowFocusChanged(boolean);
|
||||
method public void dispatchWindowInsetsAnimationFinish(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation);
|
||||
method public void dispatchWindowInsetsAnimationPrepare(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation);
|
||||
method @NonNull public android.view.WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull android.view.WindowInsets);
|
||||
method @NonNull public android.view.WindowInsetsAnimationCallback.AnimationBounds dispatchWindowInsetsAnimationStart(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation, @NonNull android.view.WindowInsetsAnimationCallback.AnimationBounds);
|
||||
method public void dispatchWindowInsetsAnimationEnd(@NonNull android.view.WindowInsetsAnimation);
|
||||
method public void dispatchWindowInsetsAnimationPrepare(@NonNull android.view.WindowInsetsAnimation);
|
||||
method @NonNull public android.view.WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull android.view.WindowInsets, @NonNull java.util.List<android.view.WindowInsetsAnimation>);
|
||||
method @NonNull public android.view.WindowInsetsAnimation.Bounds dispatchWindowInsetsAnimationStart(@NonNull android.view.WindowInsetsAnimation, @NonNull android.view.WindowInsetsAnimation.Bounds);
|
||||
method @Deprecated public void dispatchWindowSystemUiVisiblityChanged(int);
|
||||
method public void dispatchWindowVisibilityChanged(int);
|
||||
method @CallSuper public void draw(android.graphics.Canvas);
|
||||
@@ -54065,7 +54065,7 @@ package android.view {
|
||||
method public void setVisibility(int);
|
||||
method @Deprecated public void setWillNotCacheDrawing(boolean);
|
||||
method public void setWillNotDraw(boolean);
|
||||
method public void setWindowInsetsAnimationCallback(@Nullable android.view.WindowInsetsAnimationCallback);
|
||||
method public void setWindowInsetsAnimationCallback(@Nullable android.view.WindowInsetsAnimation.Callback);
|
||||
method public void setX(float);
|
||||
method public void setY(float);
|
||||
method public void setZ(float);
|
||||
@@ -55232,25 +55232,8 @@ package android.view {
|
||||
method public static int tappableElement();
|
||||
}
|
||||
|
||||
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 {
|
||||
ctor public WindowInsetsAnimationCallback.AnimationBounds(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
|
||||
method @NonNull public android.graphics.Insets getLowerBound();
|
||||
method @NonNull public android.graphics.Insets getUpperBound();
|
||||
method @NonNull public android.view.WindowInsetsAnimationCallback.AnimationBounds inset(@NonNull android.graphics.Insets);
|
||||
}
|
||||
|
||||
public static final class WindowInsetsAnimationCallback.InsetsAnimation {
|
||||
ctor public WindowInsetsAnimationCallback.InsetsAnimation(int, @Nullable android.view.animation.Interpolator, long);
|
||||
public final class WindowInsetsAnimation {
|
||||
ctor public WindowInsetsAnimation(int, @Nullable android.view.animation.Interpolator, long);
|
||||
method @FloatRange(from=0.0f, to=1.0f) public float getAlpha();
|
||||
method public long getDurationMillis();
|
||||
method @FloatRange(from=0.0f, to=1.0f) public float getFraction();
|
||||
@@ -55261,6 +55244,24 @@ package android.view {
|
||||
method public void setFraction(@FloatRange(from=0.0f, to=1.0f) float);
|
||||
}
|
||||
|
||||
public static final class WindowInsetsAnimation.Bounds {
|
||||
ctor public WindowInsetsAnimation.Bounds(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
|
||||
method @NonNull public android.graphics.Insets getLowerBound();
|
||||
method @NonNull public android.graphics.Insets getUpperBound();
|
||||
method @NonNull public android.view.WindowInsetsAnimation.Bounds inset(@NonNull android.graphics.Insets);
|
||||
}
|
||||
|
||||
public abstract static class WindowInsetsAnimation.Callback {
|
||||
ctor public WindowInsetsAnimation.Callback(int);
|
||||
method public final int getDispatchMode();
|
||||
method public void onEnd(@NonNull android.view.WindowInsetsAnimation);
|
||||
method public void onPrepare(@NonNull android.view.WindowInsetsAnimation);
|
||||
method @NonNull public abstract android.view.WindowInsets onProgress(@NonNull android.view.WindowInsets, @NonNull java.util.List<android.view.WindowInsetsAnimation>);
|
||||
method @NonNull public android.view.WindowInsetsAnimation.Bounds onStart(@NonNull android.view.WindowInsetsAnimation, @NonNull android.view.WindowInsetsAnimation.Bounds);
|
||||
field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1
|
||||
field public static final int DISPATCH_MODE_STOP = 0; // 0x0
|
||||
}
|
||||
|
||||
public interface WindowInsetsAnimationControlListener {
|
||||
method public void onCancelled();
|
||||
method public void onReady(@NonNull android.view.WindowInsetsAnimationController, int);
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
package android.view;
|
||||
|
||||
import android.view.InsetsController.LayoutInsetsDuringAnimation;
|
||||
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
|
||||
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
|
||||
/**
|
||||
* Provide an interface to let InsetsAnimationControlImpl call back into its owner.
|
||||
@@ -29,15 +28,16 @@ public interface InsetsAnimationControlCallbacks {
|
||||
/**
|
||||
* Executes the necessary code to start the animation in the correct order, including:
|
||||
* <ul>
|
||||
* <li>Dispatch {@link WindowInsetsAnimationCallback#onPrepare}</li>
|
||||
* <li>Dispatch {@link WindowInsetsAnimation.Callback#onPrepare}</li>
|
||||
* <li>Update insets state and run layout according to {@code layoutDuringAnimation}</li>
|
||||
* <li>Dispatch {@link WindowInsetsAnimationCallback#onStart}</li>
|
||||
* <li>Dispatch {@link WindowInsetsAnimation.Callback#onStart}</li>
|
||||
* <li>Dispatch {@link WindowInsetsAnimationControlListener#onReady}</li>
|
||||
* </ul>
|
||||
*/
|
||||
void startAnimation(InsetsAnimationControlImpl controller,
|
||||
WindowInsetsAnimationControlListener listener, int types, InsetsAnimation animation,
|
||||
AnimationBounds bounds, @LayoutInsetsDuringAnimation int layoutDuringAnimation);
|
||||
WindowInsetsAnimationControlListener listener, int types,
|
||||
WindowInsetsAnimation animation,
|
||||
Bounds bounds, @LayoutInsetsDuringAnimation int layoutDuringAnimation);
|
||||
|
||||
/**
|
||||
* Schedule the apply by posting the animation callback.
|
||||
|
||||
@@ -35,8 +35,7 @@ import android.view.InsetsState.InternalInsetsSide;
|
||||
import android.view.InsetsState.InternalInsetsType;
|
||||
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
|
||||
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
@@ -67,7 +66,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
private final InsetsState mInitialInsetsState;
|
||||
private final @InsetsType int mTypes;
|
||||
private final InsetsAnimationControlCallbacks mController;
|
||||
private final WindowInsetsAnimationCallback.InsetsAnimation mAnimation;
|
||||
private final WindowInsetsAnimation mAnimation;
|
||||
private final Rect mFrame;
|
||||
private final boolean mFade;
|
||||
private Insets mCurrentInsets;
|
||||
@@ -100,11 +99,11 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
mFrame = new Rect(frame);
|
||||
buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls);
|
||||
|
||||
mAnimation = new WindowInsetsAnimationCallback.InsetsAnimation(mTypes, interpolator,
|
||||
mAnimation = new WindowInsetsAnimation(mTypes, interpolator,
|
||||
durationMs);
|
||||
mAnimation.setAlpha(getCurrentAlpha());
|
||||
mController.startAnimation(this, listener, types, mAnimation,
|
||||
new AnimationBounds(mHiddenInsets, mShownInsets), layoutInsetsDuringAnimation);
|
||||
new Bounds(mHiddenInsets, mShownInsets), layoutInsetsDuringAnimation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,7 +211,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
||||
return mCancelled;
|
||||
}
|
||||
|
||||
InsetsAnimation getAnimation() {
|
||||
WindowInsetsAnimation getAnimation() {
|
||||
return mAnimation;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,7 @@ import android.view.SurfaceControl.Transaction;
|
||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
|
||||
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
@@ -58,6 +57,8 @@ import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
@@ -275,6 +276,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
|
||||
private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
|
||||
private final ArrayList<RunningAnimation> mRunningAnimations = new ArrayList<>();
|
||||
private final ArrayList<WindowInsetsAnimation> mRunningInsetsAnimations = new ArrayList<>();
|
||||
private final List<WindowInsetsAnimation> mUnmodifiableRunningInsetsAnimations =
|
||||
Collections.unmodifiableList(mRunningInsetsAnimations);
|
||||
private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>();
|
||||
private WindowInsets mLastInsets;
|
||||
|
||||
@@ -337,10 +341,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
mLastInsets.shouldAlwaysConsumeSystemBars(), mLastInsets.getDisplayCutout(),
|
||||
mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode,
|
||||
mLastLegacySystemUiFlags, null /* typeSideMap */);
|
||||
mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets);
|
||||
mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets,
|
||||
mUnmodifiableRunningInsetsAnimations);
|
||||
|
||||
for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) {
|
||||
dispatchAnimationFinished(mTmpFinishedControls.get(i).getAnimation());
|
||||
dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -579,6 +584,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
|
||||
layoutInsetsDuringAnimation);
|
||||
mRunningAnimations.add(new RunningAnimation(controller, animationType));
|
||||
mRunningInsetsAnimations.add(controller.getAnimation());
|
||||
cancellationSignal.setOnCancelListener(controller::onCancelled);
|
||||
return cancellationSignal;
|
||||
}
|
||||
@@ -729,6 +735,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
if (mRunningAnimations.get(i).control == control) {
|
||||
mRunningAnimations.remove(i);
|
||||
mRunningInsetsAnimations.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -875,8 +882,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
@VisibleForTesting
|
||||
@Override
|
||||
public void startAnimation(InsetsAnimationControlImpl controller,
|
||||
WindowInsetsAnimationControlListener listener, int types, InsetsAnimation animation,
|
||||
AnimationBounds bounds, int layoutDuringAnimation) {
|
||||
WindowInsetsAnimationControlListener listener, int types,
|
||||
WindowInsetsAnimation animation, Bounds bounds, int layoutDuringAnimation) {
|
||||
if (layoutDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
|
||||
showDirectly(types);
|
||||
} else {
|
||||
@@ -904,8 +911,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void dispatchAnimationFinished(InsetsAnimation animation) {
|
||||
mViewRoot.mView.dispatchWindowInsetsAnimationFinish(animation);
|
||||
public void dispatchAnimationEnd(WindowInsetsAnimation animation) {
|
||||
mViewRoot.mView.dispatchWindowInsetsAnimationEnd(animation);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -112,8 +112,7 @@ import android.view.AccessibilityIterators.WordTextSegmentIterator;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.Window.OnContentApplyWindowInsetsListener;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
|
||||
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityEventSource;
|
||||
@@ -4672,7 +4671,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
|
||||
private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
|
||||
|
||||
WindowInsetsAnimationCallback mWindowInsetsAnimationCallback;
|
||||
WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
|
||||
|
||||
/**
|
||||
* This lives here since it's only valid for interactive views.
|
||||
@@ -11200,43 +11199,45 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link WindowInsetsAnimationCallback} to be notified about animations of windows that
|
||||
* Sets a {@link WindowInsetsAnimation.Callback} 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.
|
||||
* The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
|
||||
* dispatch mode} will affect whether animation callbacks are dispatched to the children of
|
||||
* this view.
|
||||
* </p>
|
||||
* @param listener The listener to set.
|
||||
* @param callback The callback to set.
|
||||
*/
|
||||
public void setWindowInsetsAnimationCallback(@Nullable WindowInsetsAnimationCallback listener) {
|
||||
getListenerInfo().mWindowInsetsAnimationCallback = listener;
|
||||
public void setWindowInsetsAnimationCallback(
|
||||
@Nullable WindowInsetsAnimation.Callback callback) {
|
||||
getListenerInfo().mWindowInsetsAnimationCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches {@link WindowInsetsAnimationCallback#onPrepare(InsetsAnimation)}
|
||||
* Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
|
||||
* when Window Insets animation is being prepared.
|
||||
* @param animation current animation
|
||||
*
|
||||
* @see WindowInsetsAnimationCallback#onPrepare(InsetsAnimation)
|
||||
* @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
|
||||
*/
|
||||
public void dispatchWindowInsetsAnimationPrepare(
|
||||
@NonNull InsetsAnimation animation) {
|
||||
@NonNull WindowInsetsAnimation animation) {
|
||||
if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
|
||||
mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches {@link WindowInsetsAnimationCallback#onStart(InsetsAnimation, AnimationBounds)}
|
||||
* Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
|
||||
* when Window Insets animation is started.
|
||||
* @param animation current animation
|
||||
* @param bounds the upper and lower {@link AnimationBounds} that provides range of
|
||||
* {@link InsetsAnimation}.
|
||||
* @return the upper and lower {@link AnimationBounds}.
|
||||
* @param bounds the upper and lower {@link Bounds} that provides range of
|
||||
* {@link WindowInsetsAnimation}.
|
||||
* @return the upper and lower {@link Bounds}.
|
||||
*/
|
||||
@NonNull
|
||||
public AnimationBounds dispatchWindowInsetsAnimationStart(
|
||||
@NonNull InsetsAnimation animation, @NonNull AnimationBounds bounds) {
|
||||
public Bounds dispatchWindowInsetsAnimationStart(
|
||||
@NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
|
||||
if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
|
||||
return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
|
||||
}
|
||||
@@ -11244,28 +11245,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches {@link WindowInsetsAnimationCallback#onProgress(WindowInsets)}
|
||||
* Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
|
||||
* when Window Insets animation makes progress.
|
||||
* @param insets The current {@link WindowInsets}.
|
||||
* @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
|
||||
* @return current {@link WindowInsets}.
|
||||
*/
|
||||
@NonNull
|
||||
public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets) {
|
||||
public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
|
||||
@NonNull List<WindowInsetsAnimation> runningAnimations) {
|
||||
if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
|
||||
return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets);
|
||||
return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
|
||||
runningAnimations);
|
||||
} else {
|
||||
return insets;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches {@link WindowInsetsAnimationCallback#onFinish(InsetsAnimation)}
|
||||
* when Window Insets animation finishes.
|
||||
* @param animation The current ongoing {@link InsetsAnimation}.
|
||||
* Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
|
||||
* when Window Insets animation ends.
|
||||
* @param animation The current ongoing {@link WindowInsetsAnimation}.
|
||||
*/
|
||||
public void dispatchWindowInsetsAnimationFinish(@NonNull InsetsAnimation animation) {
|
||||
public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
|
||||
if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
|
||||
mListenerInfo.mWindowInsetsAnimationCallback.onFinish(animation);
|
||||
mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
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 static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE;
|
||||
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.annotation.CallSuper;
|
||||
@@ -48,17 +48,14 @@ 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;
|
||||
import android.util.Pools.SynchronizedPool;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.Window.OnContentApplyWindowInsetsListener;
|
||||
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
|
||||
import android.view.WindowInsetsAnimationCallback.DispatchMode;
|
||||
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
import android.view.WindowInsetsAnimation.Callback.DispatchMode;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
@@ -615,7 +612,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
/**
|
||||
* Current dispatch mode of animation events
|
||||
*
|
||||
* @see WindowInsetsAnimationCallback#getDispatchMode()
|
||||
* @see WindowInsetsAnimation.Callback#getDispatchMode()
|
||||
*/
|
||||
private @DispatchMode int mInsetsAnimationDispatchMode = DISPATCH_MODE_CONTINUE_ON_SUBTREE;
|
||||
|
||||
@@ -7228,16 +7225,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWindowInsetsAnimationCallback(@Nullable WindowInsetsAnimationCallback listener) {
|
||||
super.setWindowInsetsAnimationCallback(listener);
|
||||
mInsetsAnimationDispatchMode = listener != null
|
||||
? listener.getDispatchMode()
|
||||
public void setWindowInsetsAnimationCallback(
|
||||
@Nullable WindowInsetsAnimation.Callback callback) {
|
||||
super.setWindowInsetsAnimationCallback(callback);
|
||||
mInsetsAnimationDispatchMode = callback != null
|
||||
? callback.getDispatchMode()
|
||||
: DISPATCH_MODE_CONTINUE_ON_SUBTREE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchWindowInsetsAnimationPrepare(
|
||||
@NonNull InsetsAnimation animation) {
|
||||
@NonNull WindowInsetsAnimation animation) {
|
||||
super.dispatchWindowInsetsAnimationPrepare(animation);
|
||||
|
||||
// If we are root-level content view that fits insets, set dispatch mode to stop to imitate
|
||||
@@ -7262,8 +7260,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public AnimationBounds dispatchWindowInsetsAnimationStart(
|
||||
@NonNull InsetsAnimation animation, @NonNull AnimationBounds bounds) {
|
||||
public Bounds dispatchWindowInsetsAnimationStart(
|
||||
@NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
|
||||
bounds = super.dispatchWindowInsetsAnimationStart(animation, bounds);
|
||||
if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) {
|
||||
return bounds;
|
||||
@@ -7277,27 +7275,28 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets) {
|
||||
insets = super.dispatchWindowInsetsAnimationProgress(insets);
|
||||
public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
|
||||
@NonNull List<WindowInsetsAnimation> runningAnimations) {
|
||||
insets = super.dispatchWindowInsetsAnimationProgress(insets, runningAnimations);
|
||||
if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) {
|
||||
return insets;
|
||||
}
|
||||
final int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
getChildAt(i).dispatchWindowInsetsAnimationProgress(insets);
|
||||
getChildAt(i).dispatchWindowInsetsAnimationProgress(insets, runningAnimations);
|
||||
}
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchWindowInsetsAnimationFinish(@NonNull InsetsAnimation animation) {
|
||||
super.dispatchWindowInsetsAnimationFinish(animation);
|
||||
public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
|
||||
super.dispatchWindowInsetsAnimationEnd(animation);
|
||||
if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) {
|
||||
return;
|
||||
}
|
||||
final int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
getChildAt(i).dispatchWindowInsetsAnimationFinish(animation);
|
||||
getChildAt(i).dispatchWindowInsetsAnimationEnd(animation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
432
core/java/android/view/WindowInsetsAnimation.java
Normal file
432
core/java/android/view/WindowInsetsAnimation.java
Normal file
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.view;
|
||||
|
||||
import android.annotation.FloatRange;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Insets;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class representing an animation of a set of windows that cause insets.
|
||||
*/
|
||||
public final class WindowInsetsAnimation {
|
||||
|
||||
@WindowInsets.Type.InsetsType
|
||||
private final int mTypeMask;
|
||||
private float mFraction;
|
||||
@Nullable
|
||||
private final Interpolator mInterpolator;
|
||||
private final long mDurationMillis;
|
||||
private float mAlpha;
|
||||
|
||||
/**
|
||||
* Creates a new {@link WindowInsetsAnimation} object.
|
||||
* <p>
|
||||
* This should only be used for testing, as usually the system creates this object for the
|
||||
* application to listen to with {@link Callback}.
|
||||
* </p>
|
||||
* @param typeMask The bitmask of {@link WindowInsets.Type}s that are animating.
|
||||
* @param interpolator The interpolator of the animation.
|
||||
* @param durationMillis The duration of the animation in
|
||||
* {@link java.util.concurrent.TimeUnit#MILLISECONDS}.
|
||||
*/
|
||||
public WindowInsetsAnimation(
|
||||
@WindowInsets.Type.InsetsType int typeMask, @Nullable Interpolator interpolator,
|
||||
long durationMillis) {
|
||||
mTypeMask = typeMask;
|
||||
mInterpolator = interpolator;
|
||||
mDurationMillis = durationMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The bitmask of {@link WindowInsets.Type.InsetsType}s that are animating.
|
||||
*/
|
||||
@WindowInsets.Type.InsetsType
|
||||
public int getTypeMask() {
|
||||
return mTypeMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw fractional progress of this animation between
|
||||
* start state of the animation and the end state of the animation. Note
|
||||
* that this progress is the global progress of the animation, whereas
|
||||
* {@link Callback#onProgress} will only dispatch the insets that may
|
||||
* be inset with {@link WindowInsets#inset} by parents of views in the hierarchy.
|
||||
* Progress per insets animation is global for the entire animation. One animation animates
|
||||
* all things together (in, out, ...). If they don't animate together, we'd have
|
||||
* multiple animations.
|
||||
* <p>
|
||||
* Note: In case the application is controlling the animation, the valued returned here will
|
||||
* be the same as the application passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}.
|
||||
* </p>
|
||||
* @return The current progress of this animation.
|
||||
*/
|
||||
@FloatRange(from = 0f, to = 1f)
|
||||
public float getFraction() {
|
||||
return mFraction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolated fractional progress of this animation between
|
||||
* start state of the animation and the end state of the animation. Note
|
||||
* that this progress is the global progress of the animation, whereas
|
||||
* {@link Callback#onProgress} will only dispatch the insets that may
|
||||
* be inset with {@link WindowInsets#inset} by parents of views in the hierarchy.
|
||||
* Progress per insets animation is global for the entire animation. One animation animates
|
||||
* all things together (in, out, ...). If they don't animate together, we'd have
|
||||
* multiple animations.
|
||||
* <p>
|
||||
* Note: In case the application is controlling the animation, the valued returned here will
|
||||
* be the same as the application passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)},
|
||||
* interpolated with the interpolator passed into
|
||||
* {@link WindowInsetsController#controlWindowInsetsAnimation}.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note: For system-initiated animations, this will always return a valid value between 0
|
||||
* and 1.
|
||||
* </p>
|
||||
* @see #getFraction() for raw fraction.
|
||||
* @return The current interpolated progress of this animation. -1 if interpolator isn't
|
||||
* specified.
|
||||
*/
|
||||
public float getInterpolatedFraction() {
|
||||
if (mInterpolator != null) {
|
||||
return mInterpolator.getInterpolation(mFraction);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the interpolator used for this animation, or {@code null} if this animation
|
||||
* doesn't follow an interpolation curved. For system-initiated animations, this will never
|
||||
* return {@code null}.
|
||||
*
|
||||
* @return The interpolator used for this animation.
|
||||
*/
|
||||
@Nullable
|
||||
public Interpolator getInterpolator() {
|
||||
return mInterpolator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return duration of animation in {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or
|
||||
* -1 if the animation doesn't have a fixed duration.
|
||||
*/
|
||||
public long getDurationMillis() {
|
||||
return mDurationMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fraction of the progress if {@link WindowInsets.Type.InsetsType} animation is
|
||||
* controlled by the app.
|
||||
* <p>
|
||||
* Note: This should only be used for testing, as the system fills in the fraction for the
|
||||
* application or the fraction that was passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)} is being
|
||||
* used.
|
||||
* </p>
|
||||
* @param fraction fractional progress between 0 and 1 where 0 represents hidden and
|
||||
* zero progress and 1 represent fully shown final state.
|
||||
* @see #getFraction()
|
||||
*/
|
||||
public void setFraction(@FloatRange(from = 0f, to = 1f) float fraction) {
|
||||
mFraction = fraction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the translucency of the windows that are animating.
|
||||
*
|
||||
* @return Alpha of windows that cause insets of type {@link WindowInsets.Type.InsetsType}.
|
||||
*/
|
||||
@FloatRange(from = 0f, to = 1f)
|
||||
public float getAlpha() {
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the translucency of the windows that are animating.
|
||||
* <p>
|
||||
* Note: This should only be used for testing, as the system fills in the alpha for the
|
||||
* application or the alpha that was passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)} is being
|
||||
* used.
|
||||
* </p>
|
||||
* @param alpha Alpha of windows that cause insets of type
|
||||
* {@link WindowInsets.Type.InsetsType}.
|
||||
* @see #getAlpha()
|
||||
*/
|
||||
public void setAlpha(@FloatRange(from = 0f, to = 1f) float alpha) {
|
||||
mAlpha = alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing the range of an {@link WindowInsetsAnimation}
|
||||
*/
|
||||
public static final class Bounds {
|
||||
|
||||
private final Insets mLowerBound;
|
||||
private final Insets mUpperBound;
|
||||
|
||||
public Bounds(@NonNull Insets lowerBound, @NonNull Insets upperBound) {
|
||||
mLowerBound = lowerBound;
|
||||
mUpperBound = upperBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the lower inset bound of the animation. If the animation is about showing or
|
||||
* hiding a window that cause insets, the lower bound is {@link Insets#NONE} and the upper
|
||||
* bound is the same as {@link WindowInsets#getInsets(int)} for the fully shown state. This
|
||||
* is the same as {@link WindowInsetsAnimationController#getHiddenStateInsets} and
|
||||
* {@link WindowInsetsAnimationController#getShownStateInsets} in case the listener gets
|
||||
* invoked because of an animation that originates from
|
||||
* {@link WindowInsetsAnimationController}.
|
||||
* <p>
|
||||
* However, if the size of a window that causes insets is changing, these are the
|
||||
* lower/upper bounds of that size animation.
|
||||
* </p>
|
||||
* There are no overlapping animations for a specific type, but there may be multiple
|
||||
* animations running at the same time for different inset types.
|
||||
*
|
||||
* @see #getUpperBound()
|
||||
* @see WindowInsetsAnimationController#getHiddenStateInsets
|
||||
*/
|
||||
@NonNull
|
||||
public Insets getLowerBound() {
|
||||
return mLowerBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the upper inset bound of the animation. If the animation is about showing or
|
||||
* hiding a window that cause insets, the lower bound is {@link Insets#NONE}
|
||||
* nd the upper bound is the same as {@link WindowInsets#getInsets(int)} for the fully
|
||||
* shown state. This is the same as
|
||||
* {@link WindowInsetsAnimationController#getHiddenStateInsets} and
|
||||
* {@link WindowInsetsAnimationController#getShownStateInsets} in case the listener gets
|
||||
* invoked because of an animation that originates from
|
||||
* {@link WindowInsetsAnimationController}.
|
||||
* <p>
|
||||
* However, if the size of a window that causes insets is changing, these are the
|
||||
* lower/upper bounds of that size animation.
|
||||
* <p>
|
||||
* There are no overlapping animations for a specific type, but there may be multiple
|
||||
* animations running at the same time for different inset types.
|
||||
*
|
||||
* @see #getLowerBound()
|
||||
* @see WindowInsetsAnimationController#getShownStateInsets
|
||||
*/
|
||||
@NonNull
|
||||
public Insets getUpperBound() {
|
||||
return mUpperBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insets both the lower and upper bound by the specified insets. This is to be used in
|
||||
* {@link Callback#onStart} to indicate that a part of the insets has
|
||||
* been used to offset or clip its children, and the children shouldn't worry about that
|
||||
* part anymore.
|
||||
*
|
||||
* @param insets The amount to inset.
|
||||
* @return A copy of this instance inset in the given directions.
|
||||
* @see WindowInsets#inset
|
||||
* @see Callback#onStart
|
||||
*/
|
||||
@NonNull
|
||||
public Bounds inset(@NonNull Insets insets) {
|
||||
return new Bounds(
|
||||
// TODO: refactor so that WindowInsets.insetInsets() is in a more appropriate
|
||||
// place eventually.
|
||||
WindowInsets.insetInsets(
|
||||
mLowerBound, insets.left, insets.top, insets.right, insets.bottom),
|
||||
WindowInsets.insetInsets(
|
||||
mUpperBound, insets.left, insets.top, insets.right, insets.bottom));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface that allows the application to listen to animation events for windows that cause
|
||||
* insets.
|
||||
*/
|
||||
@SuppressLint("CallbackMethodName") // TODO(b/149430296) Should be on method, not class.
|
||||
public abstract static class Callback {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static final int DISPATCH_MODE_STOP = 0;
|
||||
|
||||
/**
|
||||
* Return value for {@link #getDispatchMode()}: Dispatching of animation events should
|
||||
* continue in the view hierarchy.
|
||||
*/
|
||||
public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "DISPATCH_MODE_" }, value = {
|
||||
DISPATCH_MODE_STOP,
|
||||
DISPATCH_MODE_CONTINUE_ON_SUBTREE
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface DispatchMode {}
|
||||
|
||||
@DispatchMode
|
||||
private final int mDispatchMode;
|
||||
|
||||
/**
|
||||
* Creates a new {@link WindowInsetsAnimation} callback with the given
|
||||
* {@link #getDispatchMode() dispatch mode}.
|
||||
*
|
||||
* @param dispatchMode The dispatch mode for this callback. See {@link #getDispatchMode()}.
|
||||
*/
|
||||
public Callback(@DispatchMode int dispatchMode) {
|
||||
mDispatchMode = 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>
|
||||
* Also note that {@link #DISPATCH_MODE_STOP} 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
|
||||
@SuppressLint("CallbackMethodName") // TODO(b/149430296) False positive: not a callback.
|
||||
public final int getDispatchMode() {
|
||||
return mDispatchMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 following:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <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>
|
||||
* <li>View hierarchy gets laid out according to the changes the application has
|
||||
* requested due to the new insets being dispatched</li>
|
||||
* <li>{@link #onStart} is called <em>before</em> the view
|
||||
* hierarchy gets drawn in the new laid out state</li>
|
||||
* <li>{@link #onProgress} is called immediately after with the animation start
|
||||
* state</li>
|
||||
* <li>The frame gets drawn.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This ordering allows the application to inspect the end state after the animation has
|
||||
* finished, and then revert to the starting state of the animation in the first
|
||||
* {@link #onProgress} callback by using post-layout view properties like {@link View#setX}
|
||||
* and related methods.
|
||||
* <p>
|
||||
* Note: If the animation is application controlled by using
|
||||
* {@link WindowInsetsController#controlWindowInsetsAnimation}, the end state of the
|
||||
* animation is undefined as the application may decide on the end state only by passing in
|
||||
* {@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#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 WindowInsets.Type#ime}.
|
||||
*
|
||||
* @param animation The animation that is about to start.
|
||||
*/
|
||||
public void onPrepare(@NonNull WindowInsetsAnimation animation) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an insets animation gets started.
|
||||
* <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 may return a modified
|
||||
* instance of the bounds by calling {@link Bounds#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. 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.
|
||||
* @return The animation representing the part of the insets that should be dispatched to
|
||||
* the subtree of the hierarchy.
|
||||
*/
|
||||
@NonNull
|
||||
public Bounds onStart(
|
||||
@NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the insets change as part of running an animation. Note that even if multiple
|
||||
* animations for different types are running, there will only be one progress callback per
|
||||
* frame. The {@code insets} passed as an argument represents the overall state and will
|
||||
* include all types, regardless of whether they are animating or not.
|
||||
* <p>
|
||||
* Note that insets dispatch is hierarchical: It will start at the root of the view
|
||||
* hierarchy, and then traverse it and invoke the callback of the specific {@link View}
|
||||
* being traversed. 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. Furthermore, if {@link #getDispatchMode()} returns
|
||||
* {@link #DISPATCH_MODE_STOP}, children of this view will not receive the callback anymore.
|
||||
*
|
||||
* @param insets The current insets.
|
||||
* @param runningAnimations The currently running animations.
|
||||
* @return The insets to dispatch to the subtree of the hierarchy.
|
||||
*/
|
||||
@NonNull
|
||||
public abstract WindowInsets onProgress(@NonNull WindowInsets insets,
|
||||
@NonNull List<WindowInsetsAnimation> runningAnimations);
|
||||
|
||||
/**
|
||||
* Called when an insets animation has ended.
|
||||
*
|
||||
* @param animation The animation that has ended. This will be the same instance
|
||||
* as passed into {@link #onStart}
|
||||
*/
|
||||
public void onEnd(@NonNull WindowInsetsAnimation animation) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,412 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.view;
|
||||
|
||||
import android.annotation.FloatRange;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Insets;
|
||||
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
|
||||
* following:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <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>
|
||||
* <li>View hierarchy gets laid out according to the changes the application has requested
|
||||
* due to the new insets being dispatched</li>
|
||||
* <li>{@link #onStart} is called <em>before</em> the view
|
||||
* hierarchy gets drawn in the new laid out state</li>
|
||||
* <li>{@link #onProgress} is called immediately after with the animation start state</li>
|
||||
* <li>The frame gets drawn.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This ordering allows the application to inspect the end state after the animation has
|
||||
* finished, and then revert to the starting state of the animation in the first
|
||||
* {@link #onProgress} callback by using post-layout view properties like {@link View#setX} and
|
||||
* related methods.
|
||||
* <p>
|
||||
* Note: If the animation is application controlled by using
|
||||
* {@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#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}.
|
||||
*
|
||||
* @param animation The animation that is about to start.
|
||||
*/
|
||||
default void onPrepare(@NonNull InsetsAnimation animation) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an insets animation gets started.
|
||||
* <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 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. 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.
|
||||
* @return The animation representing the part of the insets that should be dispatched to the
|
||||
* subtree of the hierarchy.
|
||||
*/
|
||||
@NonNull
|
||||
default AnimationBounds onStart(
|
||||
@NonNull InsetsAnimation animation, @NonNull AnimationBounds bounds) {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the insets change as part of running an animation. Note that even if multiple
|
||||
* animations for different types are running, there will only be one progress callback per
|
||||
* frame. The {@code insets} passed as an argument represents the overall state and will include
|
||||
* all types, regardless of whether they are animating or not.
|
||||
* <p>
|
||||
* Note that insets dispatch is hierarchical: It will start at the root of the view hierarchy,
|
||||
* and then traverse it and invoke the callback of the specific {@link View} being traversed.
|
||||
* 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. 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?
|
||||
* @param insets The current insets.
|
||||
* @return The insets to dispatch to the subtree of the hierarchy.
|
||||
*/
|
||||
@NonNull
|
||||
WindowInsets onProgress(@NonNull WindowInsets insets);
|
||||
|
||||
/**
|
||||
* Called when an insets animation has finished.
|
||||
*
|
||||
* @param animation The animation that has finished running. This will be the same instance as
|
||||
* passed into {@link #onStart}
|
||||
*/
|
||||
default void onFinish(@NonNull InsetsAnimation animation) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing an animation of a set of windows that cause insets.
|
||||
*/
|
||||
final class InsetsAnimation {
|
||||
|
||||
private final @InsetsType int mTypeMask;
|
||||
private float mFraction;
|
||||
@Nullable private final Interpolator mInterpolator;
|
||||
private final long mDurationMillis;
|
||||
private float mAlpha;
|
||||
|
||||
/**
|
||||
* Creates a new {@link InsetsAnimation} object.
|
||||
* <p>
|
||||
* This should only be used for testing, as usually the system creates this object for the
|
||||
* application to listen to with {@link WindowInsetsAnimationCallback}.
|
||||
* </p>
|
||||
* @param typeMask The bitmask of {@link WindowInsets.Type}s that are animating.
|
||||
* @param interpolator The interpolator of the animation.
|
||||
* @param durationMillis The duration of the animation in
|
||||
* {@link java.util.concurrent.TimeUnit#MILLISECONDS}.
|
||||
*/
|
||||
public InsetsAnimation(
|
||||
@InsetsType int typeMask, @Nullable Interpolator interpolator,
|
||||
long durationMillis) {
|
||||
mTypeMask = typeMask;
|
||||
mInterpolator = interpolator;
|
||||
mDurationMillis = durationMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The bitmask of {@link WindowInsets.Type.InsetsType}s that are animating.
|
||||
*/
|
||||
public @InsetsType int getTypeMask() {
|
||||
return mTypeMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw fractional progress of this animation between
|
||||
* start state of the animation and the end state of the animation. Note
|
||||
* that this progress is the global progress of the animation, whereas
|
||||
* {@link WindowInsetsAnimationCallback#onProgress} will only dispatch the insets that may
|
||||
* be inset with {@link WindowInsets#inset} by parents of views in the hierarchy.
|
||||
* Progress per insets animation is global for the entire animation. One animation animates
|
||||
* all things together (in, out, ...). If they don't animate together, we'd have
|
||||
* multiple animations.
|
||||
* <p>
|
||||
* Note: In case the application is controlling the animation, the valued returned here will
|
||||
* be the same as the application passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}.
|
||||
* </p>
|
||||
* @return The current progress of this animation.
|
||||
*/
|
||||
@FloatRange(from = 0f, to = 1f)
|
||||
public float getFraction() {
|
||||
return mFraction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolated fractional progress of this animation between
|
||||
* start state of the animation and the end state of the animation. Note
|
||||
* that this progress is the global progress of the animation, whereas
|
||||
* {@link WindowInsetsAnimationCallback#onProgress} will only dispatch the insets that may
|
||||
* be inset with {@link WindowInsets#inset} by parents of views in the hierarchy.
|
||||
* Progress per insets animation is global for the entire animation. One animation animates
|
||||
* all things together (in, out, ...). If they don't animate together, we'd have
|
||||
* multiple animations.
|
||||
* <p>
|
||||
* Note: In case the application is controlling the animation, the valued returned here will
|
||||
* be the same as the application passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)},
|
||||
* interpolated with the interpolator passed into
|
||||
* {@link WindowInsetsController#controlWindowInsetsAnimation}.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note: For system-initiated animations, this will always return a valid value between 0
|
||||
* and 1.
|
||||
* </p>
|
||||
* @see #getFraction() for raw fraction.
|
||||
* @return The current interpolated progress of this animation. -1 if interpolator isn't
|
||||
* specified.
|
||||
*/
|
||||
public float getInterpolatedFraction() {
|
||||
if (mInterpolator != null) {
|
||||
return mInterpolator.getInterpolation(mFraction);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the interpolator used for this animation, or {@code null} if this animation
|
||||
* doesn't follow an interpolation curved. For system-initiated animations, this will never
|
||||
* return {@code null}.
|
||||
*
|
||||
* @return The interpolator used for this animation.
|
||||
*/
|
||||
@Nullable
|
||||
public Interpolator getInterpolator() {
|
||||
return mInterpolator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return duration of animation in {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or
|
||||
* -1 if the animation doesn't have a fixed duration.
|
||||
*/
|
||||
public long getDurationMillis() {
|
||||
return mDurationMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fraction of the progress if {@link WindowInsets.Type.InsetsType} animation is
|
||||
* controlled by the app.
|
||||
* <p>
|
||||
* Note: This should only be used for testing, as the system fills in the fraction for the
|
||||
* application or the fraction that was passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)} is being
|
||||
* used.
|
||||
* </p>
|
||||
* @param fraction fractional progress between 0 and 1 where 0 represents hidden and
|
||||
* zero progress and 1 represent fully shown final state.
|
||||
* @see #getFraction()
|
||||
*/
|
||||
public void setFraction(@FloatRange(from = 0f, to = 1f) float fraction) {
|
||||
mFraction = fraction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the translucency of the windows that are animating.
|
||||
*
|
||||
* @return Alpha of windows that cause insets of type {@link WindowInsets.Type.InsetsType}.
|
||||
*/
|
||||
@FloatRange(from = 0f, to = 1f)
|
||||
public float getAlpha() {
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the translucency of the windows that are animating.
|
||||
* <p>
|
||||
* Note: This should only be used for testing, as the system fills in the alpha for the
|
||||
* application or the alpha that was passed into
|
||||
* {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)} is being
|
||||
* used.
|
||||
* </p>
|
||||
* @param alpha Alpha of windows that cause insets of type
|
||||
* {@link WindowInsets.Type.InsetsType}.
|
||||
* @see #getAlpha()
|
||||
*/
|
||||
public void setAlpha(@FloatRange(from = 0f, to = 1f) float alpha) {
|
||||
mAlpha = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing the range of an {@link InsetsAnimation}
|
||||
*/
|
||||
final class AnimationBounds {
|
||||
|
||||
private final Insets mLowerBound;
|
||||
private final Insets mUpperBound;
|
||||
|
||||
public AnimationBounds(@NonNull Insets lowerBound, @NonNull Insets upperBound) {
|
||||
mLowerBound = lowerBound;
|
||||
mUpperBound = upperBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the lower inset bound of the animation. If the animation is about showing or
|
||||
* hiding a window that cause insets, the lower bound is {@link Insets#NONE} and the upper
|
||||
* bound is the same as {@link WindowInsets#getInsets(int)} for the fully shown state. This
|
||||
* is the same as {@link WindowInsetsAnimationController#getHiddenStateInsets} and
|
||||
* {@link WindowInsetsAnimationController#getShownStateInsets} in case the listener gets
|
||||
* invoked because of an animation that originates from
|
||||
* {@link WindowInsetsAnimationController}.
|
||||
* <p>
|
||||
* However, if the size of a window that causes insets is changing, these are the
|
||||
* lower/upper bounds of that size animation.
|
||||
* </p>
|
||||
* There are no overlapping animations for a specific type, but there may be multiple
|
||||
* animations running at the same time for different inset types.
|
||||
*
|
||||
* @see #getUpperBound()
|
||||
* @see WindowInsetsAnimationController#getHiddenStateInsets
|
||||
*/
|
||||
@NonNull
|
||||
public Insets getLowerBound() {
|
||||
return mLowerBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the upper inset bound of the animation. If the animation is about showing or
|
||||
* hiding a window that cause insets, the lower bound is {@link Insets#NONE}
|
||||
* nd the upper bound is the same as {@link WindowInsets#getInsets(int)} for the fully
|
||||
* shown state. This is the same as
|
||||
* {@link WindowInsetsAnimationController#getHiddenStateInsets} and
|
||||
* {@link WindowInsetsAnimationController#getShownStateInsets} in case the listener gets
|
||||
* invoked because of an animation that originates from
|
||||
* {@link WindowInsetsAnimationController}.
|
||||
* <p>
|
||||
* However, if the size of a window that causes insets is changing, these are the
|
||||
* lower/upper bounds of that size animation.
|
||||
* <p>
|
||||
* There are no overlapping animations for a specific type, but there may be multiple
|
||||
* animations running at the same time for different inset types.
|
||||
*
|
||||
* @see #getLowerBound()
|
||||
* @see WindowInsetsAnimationController#getShownStateInsets
|
||||
*/
|
||||
@NonNull
|
||||
public Insets getUpperBound() {
|
||||
return mUpperBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insets both the lower and upper bound by the specified insets. This is to be used in
|
||||
* {@link WindowInsetsAnimationCallback#onStart} to indicate that a part of the insets has
|
||||
* been used to offset or clip its children, and the children shouldn't worry about that
|
||||
* part anymore.
|
||||
*
|
||||
* @param insets The amount to inset.
|
||||
* @return A copy of this instance inset in the given directions.
|
||||
* @see WindowInsets#inset
|
||||
* @see WindowInsetsAnimationCallback#onStart
|
||||
*/
|
||||
@NonNull
|
||||
public AnimationBounds inset(@NonNull Insets insets) {
|
||||
return new AnimationBounds(
|
||||
// TODO: refactor so that WindowInsets.insetInsets() is in a more appropriate
|
||||
// place eventually.
|
||||
WindowInsets.insetInsets(
|
||||
mLowerBound, insets.left, insets.top, insets.right, insets.bottom),
|
||||
WindowInsets.insetInsets(
|
||||
mUpperBound, insets.left, insets.top, insets.right, insets.bottom));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,7 @@ import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Insets;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.WindowInsetsAnimation.Bounds;
|
||||
|
||||
/**
|
||||
* Controller for app-driven animation of system windows.
|
||||
@@ -35,7 +34,7 @@ import android.view.animation.Interpolator;
|
||||
* <p>
|
||||
* Control is obtained through {@link WindowInsetsController#controlWindowInsetsAnimation}.
|
||||
*/
|
||||
@SuppressLint("NotClosable")
|
||||
@SuppressLint("NotCloseable")
|
||||
public interface WindowInsetsAnimationController {
|
||||
|
||||
/**
|
||||
@@ -45,12 +44,12 @@ public interface WindowInsetsAnimationController {
|
||||
* to {@link View#getRootView}
|
||||
* <p>
|
||||
* If there are any animation listeners registered, this value is the same as
|
||||
* {@link AnimationBounds#getLowerBound()} that is being be passed into the root view of the
|
||||
* {@link Bounds#getLowerBound()} that is being be passed into the root view of the
|
||||
* hierarchy.
|
||||
*
|
||||
* @return Insets when the windows this animation is controlling are fully hidden.
|
||||
*
|
||||
* @see AnimationBounds#getLowerBound()
|
||||
* @see Bounds#getLowerBound()
|
||||
*/
|
||||
@NonNull Insets getHiddenStateInsets();
|
||||
|
||||
@@ -61,11 +60,11 @@ public interface WindowInsetsAnimationController {
|
||||
* to {@link View#getRootView}
|
||||
* <p>
|
||||
* If there are any animation listeners registered, this value is the same as
|
||||
* {@link AnimationBounds#getUpperBound()} that is being passed into the root view of hierarchy.
|
||||
* {@link Bounds#getUpperBound()} that is being passed into the root view of hierarchy.
|
||||
*
|
||||
* @return Insets when the windows this animation is controlling are fully shown.
|
||||
*
|
||||
* @see AnimationBounds#getUpperBound()
|
||||
* @see Bounds#getUpperBound()
|
||||
*/
|
||||
@NonNull Insets getShownStateInsets();
|
||||
|
||||
@@ -114,9 +113,9 @@ public interface WindowInsetsAnimationController {
|
||||
* Also note that this will <b>not</b> inform the view system of a full inset change via
|
||||
* {@link View#dispatchApplyWindowInsets} in order to avoid a full layout pass during the
|
||||
* animation. If you'd like to animate views during a window inset animation, register a
|
||||
* {@link WindowInsetsAnimationCallback} by calling
|
||||
* {@link View#setWindowInsetsAnimationCallback(WindowInsetsAnimationCallback)} that will be
|
||||
* notified about any insets change via {@link WindowInsetsAnimationCallback#onProgress} during
|
||||
* {@link WindowInsetsAnimation.Callback} by calling
|
||||
* {@link View#setWindowInsetsAnimationCallback(WindowInsetsAnimation.Callback)} that will be
|
||||
* notified about any insets change via {@link WindowInsetsAnimation.Callback#onProgress} during
|
||||
* the animation.
|
||||
* <p>
|
||||
* {@link View#dispatchApplyWindowInsets} will instead be called once the animation has
|
||||
@@ -131,10 +130,10 @@ public interface WindowInsetsAnimationController {
|
||||
* If you intend on changing alpha only, pass null or {@link #getCurrentInsets()}.
|
||||
* @param alpha The new alpha to apply to the inset side.
|
||||
* @param fraction instantaneous animation progress. This value is dispatched to
|
||||
* {@link WindowInsetsAnimationCallback}.
|
||||
* {@link WindowInsetsAnimation.Callback}.
|
||||
*
|
||||
* @see WindowInsetsAnimationCallback
|
||||
* @see View#setWindowInsetsAnimationCallback(WindowInsetsAnimationCallback)
|
||||
* @see WindowInsetsAnimation.Callback
|
||||
* @see View#setWindowInsetsAnimationCallback(WindowInsetsAnimation.Callback)
|
||||
*/
|
||||
void setInsetsAndAlpha(@Nullable Insets insets, @FloatRange(from = 0f, to = 1f) float alpha,
|
||||
@FloatRange(from = 0f, to = 1f) float fraction);
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.annotation.Nullable;
|
||||
import android.graphics.Insets;
|
||||
import android.os.CancellationSignal;
|
||||
import android.view.WindowInsets.Type.InsetsType;
|
||||
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -148,19 +147,19 @@ public interface WindowInsetsController {
|
||||
* @param durationMillis Duration of 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()}
|
||||
* passed to {@link WindowInsetsAnimation#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()}.
|
||||
* passed to {@link WindowInsetsAnimation#getInterpolator()} and used to
|
||||
* calculate {@link WindowInsetsAnimation#getInterpolatedFraction()}.
|
||||
* @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the
|
||||
* windows are ready to be controlled, among other callbacks.
|
||||
* @return A cancellation signal that the caller can use to cancel the request to obtain
|
||||
* control, or once they have control, to cancel the control.
|
||||
* @see InsetsAnimation#getFraction()
|
||||
* @see InsetsAnimation#getInterpolatedFraction()
|
||||
* @see InsetsAnimation#getInterpolator()
|
||||
* @see InsetsAnimation#getDurationMillis()
|
||||
* @see WindowInsetsAnimation#getFraction()
|
||||
* @see WindowInsetsAnimation#getInterpolatedFraction()
|
||||
* @see WindowInsetsAnimation#getInterpolator()
|
||||
* @see WindowInsetsAnimation#getDurationMillis()
|
||||
*/
|
||||
@NonNull
|
||||
CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, long durationMillis,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.view;
|
||||
@@ -23,7 +23,6 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
|
||||
import static android.view.WindowInsets.Type.systemBars;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
|
||||
@@ -41,7 +41,7 @@ import android.view.InsetsState.InternalInsetsType;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SyncRtSurfaceTransactionApplier;
|
||||
import android.view.ViewRootImpl;
|
||||
import android.view.WindowInsetsAnimationCallback;
|
||||
import android.view.WindowInsetsAnimation;
|
||||
import android.view.WindowInsetsAnimationControlListener;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -403,8 +403,8 @@ class InsetsPolicy {
|
||||
@Override
|
||||
public void startAnimation(InsetsAnimationControlImpl controller,
|
||||
WindowInsetsAnimationControlListener listener, int types,
|
||||
WindowInsetsAnimationCallback.InsetsAnimation animation,
|
||||
WindowInsetsAnimationCallback.AnimationBounds bounds,
|
||||
WindowInsetsAnimation animation,
|
||||
WindowInsetsAnimation.Bounds bounds,
|
||||
int layoutDuringAnimation) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,26 @@
|
||||
|
||||
package com.google.android.test.windowinsetstests;
|
||||
|
||||
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Insets;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.util.Property;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowInsetsAnimationCallback;
|
||||
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
|
||||
import android.view.WindowInsetsAnimation;
|
||||
import android.view.WindowInsetsAnimationControlListener;
|
||||
import android.view.WindowInsetsAnimationController;
|
||||
|
||||
import com.google.android.test.windowinsetstests.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WindowInsetsActivity extends Activity {
|
||||
|
||||
private View mRoot;
|
||||
@@ -70,7 +72,7 @@ public class WindowInsetsActivity extends Activity {
|
||||
|
||||
float startY;
|
||||
float endY;
|
||||
InsetsAnimation imeAnim;
|
||||
WindowInsetsAnimation imeAnim;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -85,15 +87,11 @@ public class WindowInsetsActivity extends Activity {
|
||||
v.getWindowInsetsController().hide(Type.ime());
|
||||
}
|
||||
});
|
||||
mRoot.setWindowInsetsAnimationCallback(new WindowInsetsAnimationCallback() {
|
||||
mRoot.setWindowInsetsAnimationCallback(new WindowInsetsAnimation.Callback(
|
||||
DISPATCH_MODE_STOP) {
|
||||
|
||||
@Override
|
||||
public int getDispatchMode() {
|
||||
return DISPATCH_MODE_STOP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepare(InsetsAnimation animation) {
|
||||
public void onPrepare(WindowInsetsAnimation animation) {
|
||||
if ((animation.getTypeMask() & Type.ime()) != 0) {
|
||||
imeAnim = animation;
|
||||
}
|
||||
@@ -101,20 +99,21 @@ public class WindowInsetsActivity extends Activity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowInsets onProgress(WindowInsets insets) {
|
||||
public WindowInsets onProgress(WindowInsets insets,
|
||||
List<WindowInsetsAnimation> runningAnimations) {
|
||||
mButton.setY(startY + (endY - startY) * imeAnim.getInterpolatedFraction());
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimationBounds onStart(InsetsAnimation animation,
|
||||
AnimationBounds bounds) {
|
||||
public WindowInsetsAnimation.Bounds onStart(WindowInsetsAnimation animation,
|
||||
WindowInsetsAnimation.Bounds bounds) {
|
||||
endY = mButton.getTop();
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish(InsetsAnimation animation) {
|
||||
public void onEnd(WindowInsetsAnimation animation) {
|
||||
imeAnim = null;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user