summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/window/BackProgressAnimator.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt4
3 files changed, 54 insertions, 11 deletions
diff --git a/core/java/android/window/BackProgressAnimator.java b/core/java/android/window/BackProgressAnimator.java
index 6fe0784a2fa5..94d7811677ae 100644
--- a/core/java/android/window/BackProgressAnimator.java
+++ b/core/java/android/window/BackProgressAnimator.java
@@ -33,7 +33,7 @@ import com.android.internal.dynamicanimation.animation.SpringForce;
*
* @hide
*/
-public class BackProgressAnimator {
+public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateListener {
/**
* A factor to scale the input progress by, so that it works better with the spring.
* We divide the output progress by this value before sending it to apps, so that apps
@@ -43,6 +43,7 @@ public class BackProgressAnimator {
private final SpringAnimation mSpring;
private ProgressCallback mCallback;
private float mProgress = 0;
+ private float mVelocity = 0;
private BackMotionEvent mLastBackEvent;
private boolean mBackAnimationInProgress = false;
@Nullable
@@ -67,7 +68,6 @@ public class BackProgressAnimator {
@Override
public void setValue(BackProgressAnimator animator, float value) {
animator.setProgress(value);
- animator.updateProgressValue(value);
}
@Override
@@ -76,6 +76,11 @@ public class BackProgressAnimator {
}
};
+ @Override
+ public void onAnimationUpdate(DynamicAnimation animation, float value, float velocity) {
+ updateProgressValue(value, velocity);
+ }
+
/** A callback to be invoked when there's a progress value update from the animator. */
public interface ProgressCallback {
@@ -85,6 +90,7 @@ public class BackProgressAnimator {
public BackProgressAnimator() {
mSpring = new SpringAnimation(this, PROGRESS_PROP);
+ mSpring.addUpdateListener(this);
mSpring.setSpring(new SpringForce()
.setStiffness(SpringForce.STIFFNESS_MEDIUM)
.setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
@@ -117,7 +123,7 @@ public class BackProgressAnimator {
mLastBackEvent = event;
mCallback = callback;
mBackAnimationInProgress = true;
- updateProgressValue(0);
+ updateProgressValue(0, 0);
}
/**
@@ -126,7 +132,7 @@ public class BackProgressAnimator {
public void reset() {
if (mBackCancelledFinishRunnable != null) {
// Ensure that last progress value that apps see is 0
- updateProgressValue(0);
+ updateProgressValue(0, 0);
invokeBackCancelledRunnable();
}
mSpring.animateToFinalPosition(0);
@@ -167,7 +173,15 @@ public class BackProgressAnimator {
return mBackAnimationInProgress;
}
- private void updateProgressValue(float progress) {
+ /**
+ * @return The last recorded velocity. Unit: change in progress per second
+ */
+ public float getVelocity() {
+ return mVelocity / SCALE_FACTOR;
+ }
+
+ private void updateProgressValue(float progress, float velocity) {
+ mVelocity = velocity;
if (mLastBackEvent == null || mCallback == null || !mBackAnimationInProgress) {
return;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
index c988c2fb5103..71fc8c3a01ea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
@@ -41,6 +41,9 @@ import android.window.BackMotionEvent
import android.window.BackNavigationInfo
import android.window.BackProgressAnimator
import android.window.IOnBackInvokedCallback
+import com.android.internal.dynamicanimation.animation.FloatValueHolder
+import com.android.internal.dynamicanimation.animation.SpringAnimation
+import com.android.internal.dynamicanimation.animation.SpringForce
import com.android.internal.jank.Cuj
import com.android.internal.policy.ScreenDecorationsUtils
import com.android.internal.protolog.common.ProtoLog
@@ -70,6 +73,7 @@ abstract class CrossActivityBackAnimation(
protected val backAnimRect = Rect()
private val cropRect = Rect()
+ private val tempRectF = RectF()
private var cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
@@ -98,6 +102,12 @@ abstract class CrossActivityBackAnimation(
private var rightLetterboxLayer: SurfaceControl? = null
private var letterboxColor: Int = 0
+ private val postCommitFlingScale = FloatValueHolder(SPRING_SCALE)
+ private var lastPostCommitFlingScale = SPRING_SCALE
+ private val postCommitFlingSpring = SpringForce(SPRING_SCALE)
+ .setStiffness(SpringForce.STIFFNESS_LOW)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+
/** Background color to be used during the animation, also see [getBackgroundColor] */
protected var customizedBackgroundColor = 0
@@ -231,7 +241,7 @@ abstract class CrossActivityBackAnimation(
return deltaY
}
- protected open fun onGestureCommitted() {
+ protected open fun onGestureCommitted(velocity: Float) {
if (
closingTarget?.leash == null ||
enteringTarget?.leash == null ||
@@ -242,6 +252,14 @@ abstract class CrossActivityBackAnimation(
return
}
+ // kick off spring animation with the current velocity from the pre-commit phase, this
+ // affects the scaling of the closing activity during post-commit
+ val flingAnimation = SpringAnimation(postCommitFlingScale, SPRING_SCALE)
+ .setStartVelocity(min(0f, -velocity * SPRING_SCALE))
+ .setStartValue(SPRING_SCALE)
+ .setSpring(postCommitFlingSpring)
+ flingAnimation.start()
+
val valueAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(POST_COMMIT_DURATION)
valueAnimator.addUpdateListener { animation: ValueAnimator ->
val progress = animation.animatedFraction
@@ -291,6 +309,7 @@ abstract class CrossActivityBackAnimation(
removeLetterbox()
isLetterboxed = false
enteringHasSameLetterbox = false
+ lastPostCommitFlingScale = SPRING_SCALE
}
protected fun applyTransform(
@@ -300,7 +319,15 @@ abstract class CrossActivityBackAnimation(
baseTransformation: Transformation? = null
) {
if (leash == null || !leash.isValid) return
- val scale = rect.width() / backAnimRect.width()
+ tempRectF.set(rect)
+ if (leash == closingTarget?.leash) {
+ lastPostCommitFlingScale = (postCommitFlingScale.value / SPRING_SCALE).coerceIn(
+ minimumValue = MAX_FLING_SCALE, maximumValue = lastPostCommitFlingScale
+ )
+ // apply an additional scale to the closing target to account for fling velocity
+ tempRectF.scaleCentered(lastPostCommitFlingScale)
+ }
+ val scale = tempRectF.width() / backAnimRect.width()
val matrix = baseTransformation?.matrix ?: transformMatrix.apply { reset() }
val scalePivotX =
if (isLetterboxed && enteringHasSameLetterbox) {
@@ -309,7 +336,7 @@ abstract class CrossActivityBackAnimation(
0f
}
matrix.postScale(scale, scale, scalePivotX, 0f)
- matrix.postTranslate(rect.left, rect.top)
+ matrix.postTranslate(tempRectF.left, tempRectF.top)
transaction
.setAlpha(leash, keepMinimumAlpha(alpha))
.setMatrix(leash, matrix, tmpFloat9)
@@ -461,7 +488,7 @@ abstract class CrossActivityBackAnimation(
override fun onBackInvoked() {
progressAnimator.reset()
- onGestureCommitted()
+ onGestureCommitted(progressAnimator.velocity)
}
}
@@ -497,6 +524,8 @@ abstract class CrossActivityBackAnimation(
private const val MAX_SCRIM_ALPHA_DARK = 0.8f
private const val MAX_SCRIM_ALPHA_LIGHT = 0.2f
private const val POST_COMMIT_DURATION = 300L
+ private const val SPRING_SCALE = 100f
+ private const val MAX_FLING_SCALE = 0.6f
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt
index f33c5b9bd183..d6c5349201b8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt
@@ -56,7 +56,7 @@ constructor(
targetEnteringRect.scaleCentered(MAX_SCALE)
}
- override fun onGestureCommitted() {
+ override fun onGestureCommitted(velocity: Float) {
// We enter phase 2 of the animation, the starting coordinates for phase 2 are the current
// coordinate of the gesture driven phase. Let's update the start and target rects and kick
// off the animator in the superclass
@@ -65,7 +65,7 @@ constructor(
targetEnteringRect.set(backAnimRect)
targetClosingRect.set(backAnimRect)
targetClosingRect.offset(currentClosingRect.left + enteringStartOffset, 0f)
- super.onGestureCommitted()
+ super.onGestureCommitted(velocity)
}
override fun onPostCommitProgress(linearProgress: Float) {