From 056a4fcdc7306d46fc4d5ec0dff270bbf4fb2223 Mon Sep 17 00:00:00 2001 From: Arthur Hung Date: Wed, 7 Dec 2022 08:17:19 +0000 Subject: [PATCH] DO NOT MERGE Let BackProgressAnimator could play cancel animation Add cancel and the cancel callback in BackProgressAnimator so it could animate to start position and invoke the callback after finished. Bug: 259608500 Test: atest BackAnimationControllerTest BackNavigationControllerTests Test: atest BackProgressAnimatorTest Change-Id: I94303ba530d155f4b264dafa21bd23185a6b44bd --- core/java/android/window/BackEvent.java | 16 ++++++++++++- .../android/window/BackProgressAnimator.java | 23 +++++++++++++++++++ .../window/WindowOnBackInvokedDispatcher.java | 11 +++++---- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/core/java/android/window/BackEvent.java b/core/java/android/window/BackEvent.java index 4a4f561c71ede..940b133eb1696 100644 --- a/core/java/android/window/BackEvent.java +++ b/core/java/android/window/BackEvent.java @@ -99,7 +99,21 @@ public class BackEvent implements Parcelable { } /** - * Returns a value between 0 and 1 on how far along the back gesture is. + * Returns a value between 0 and 1 on how far along the back gesture is. This value is + * driven by the horizontal location of the touch point, and should be used as the fraction to + * seek the predictive back animation with. Specifically, + *
    + *
  1. The progress is 0 when the touch is at the starting edge of the screen (left or right), + * and animation should seek to its start state. + *
  2. The progress is approximately 1 when the touch is at the opposite side of the screen, + * and animation should seek to its end state. Exact end value may vary depending on + * screen size. + *
+ *
  • After the gesture finishes in cancel state, this method keeps getting invoked until the + * progress value animates back to 0. + * + * In-between locations are linearly interpolated based on horizontal distance from the starting + * edge and smooth clamped to 1 when the distance exceeds a system-wide threshold. */ public float getProgress() { return mProgress; diff --git a/core/java/android/window/BackProgressAnimator.java b/core/java/android/window/BackProgressAnimator.java index 38c52e7473f1d..b22f967e9e2a9 100644 --- a/core/java/android/window/BackProgressAnimator.java +++ b/core/java/android/window/BackProgressAnimator.java @@ -16,8 +16,10 @@ package android.window; +import android.annotation.NonNull; import android.util.FloatProperty; +import com.android.internal.dynamicanimation.animation.DynamicAnimation; import com.android.internal.dynamicanimation.animation.SpringAnimation; import com.android.internal.dynamicanimation.animation.SpringForce; @@ -123,6 +125,27 @@ public class BackProgressAnimator { mProgress = 0; } + /** + * Animate the back progress animation from current progress to start position. + * This should be called when back is cancelled. + * + * @param finishCallback the callback to be invoked when the progress is reach to 0. + */ + public void onBackCancelled(@NonNull Runnable finishCallback) { + final DynamicAnimation.OnAnimationEndListener listener = + new DynamicAnimation.OnAnimationEndListener() { + @Override + public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value, + float velocity) { + mSpring.removeEndListener(this); + finishCallback.run(); + reset(); + } + }; + mSpring.addEndListener(listener); + mSpring.animateToFinalPosition(0); + } + private void updateProgressValue(float progress) { if (mLastBackEvent == null || mCallback == null || !mStarted) { return; diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index dd9483a9c759e..bfa3447076d5f 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -255,11 +255,12 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @Override public void onBackCancelled() { Handler.getMain().post(() -> { - mProgressAnimator.reset(); - final OnBackAnimationCallback callback = getBackAnimationCallback(); - if (callback != null) { - callback.onBackCancelled(); - } + mProgressAnimator.onBackCancelled(() -> { + final OnBackAnimationCallback callback = getBackAnimationCallback(); + if (callback != null) { + callback.onBackCancelled(); + } + }); }); }