diff options
author | Kevin <kevhan@google.com> | 2019-03-13 15:49:31 -0700 |
---|---|---|
committer | Kevin <kevhan@google.com> | 2019-03-18 17:15:15 -0700 |
commit | 502847f7eb29cd8fc3f515e9e5aa2647b0d9e72f (patch) | |
tree | b508487442ef89c0abb63061514d6f901d61bdf7 /go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java | |
parent | 2ec9f290bf45aaef86edf6e31c1e070bef8b7a68 (diff) | |
download | android_packages_apps_Trebuchet-502847f7eb29cd8fc3f515e9e5aa2647b0d9e72f.tar.gz android_packages_apps_Trebuchet-502847f7eb29cd8fc3f515e9e5aa2647b0d9e72f.tar.bz2 android_packages_apps_Trebuchet-502847f7eb29cd8fc3f515e9e5aa2647b0d9e72f.zip |
Add app to overview anim for Recents Go.
This CL adds the first iteration of window animation to go from
the app back to recents provided that the view is ready to be
visible to the user.
Bug: 114136250
Test: Go to recents, launch app, press overview to go back to recents
Change-Id: Ic0567e7c87fa964bdad25d07eca61b78407a9ff5
Diffstat (limited to 'go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java')
-rw-r--r-- | go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java | 154 |
1 files changed, 147 insertions, 7 deletions
diff --git a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java index f199643bc..defed845d 100644 --- a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java +++ b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java @@ -15,15 +15,29 @@ */ package com.android.quickstep; +import static com.android.launcher3.anim.Interpolators.ACCEL_2; +import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; +import static com.android.quickstep.util.RemoteAnimationProvider.getLayer; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import android.animation.AnimatorSet; import android.animation.ValueAnimator; +import android.graphics.Matrix; +import android.graphics.Rect; import android.util.Log; +import android.view.View; + +import androidx.annotation.NonNull; import com.android.launcher3.BaseDraggingActivity; +import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RemoteAnimationProvider; +import com.android.quickstep.views.IconRecentsView; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; /** * Provider for the atomic remote window animation from the app to the overview. @@ -33,13 +47,17 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat; final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements RemoteAnimationProvider { - private static final long RECENTS_LAUNCH_DURATION = 250; + private static final long APP_TO_THUMBNAIL_FADE_DURATION = 50; + private static final long APP_SCALE_DOWN_DURATION = 400; private static final String TAG = "AppToOverviewAnimationProvider"; private final ActivityControlHelper<T> mHelper; + private final int mTargetTaskId; + private IconRecentsView mRecentsView; AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) { mHelper = helper; + mTargetTaskId = targetTaskId; } /** @@ -54,35 +72,157 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple false /* animate activity */, (controller) -> { controller.dispatchOnStart(); ValueAnimator anim = controller.getAnimationPlayer() - .setDuration(RECENTS_LAUNCH_DURATION); + .setDuration(getRecentsLaunchDuration()); anim.setInterpolator(FAST_OUT_SLOW_IN); anim.start(); }); factory.onRemoteAnimationReceived(null); - factory.createActivityController(RECENTS_LAUNCH_DURATION); + factory.createActivityController(getRecentsLaunchDuration()); + mRecentsView = activity.getOverviewPanel(); return false; } /** - * Create remote window animation from the currently running app to the overview panel. + * Create remote window animation from the currently running app to the overview panel. Should + * be called after {@link #onActivityReady}. * * @param targetCompats the target apps * @return animation from app to overview */ @Override public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) { - //TODO: Implement the overview to app window animation for Go. AnimatorSet anim = new AnimatorSet(); - anim.play(ValueAnimator.ofInt(0, 1).setDuration(RECENTS_LAUNCH_DURATION)); + if (mRecentsView == null) { + if (Log.isLoggable(TAG, Log.WARN)) { + Log.w(TAG, "No recents view. Using stub animation."); + } + anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration())); + return anim; + } + + RemoteAnimationTargetCompat recentsTarget = null; + RemoteAnimationTargetCompat closingAppTarget = null; + + for (RemoteAnimationTargetCompat target : targetCompats) { + if (target.mode == MODE_OPENING) { + recentsTarget = target; + } else if (target.mode == MODE_CLOSING && target.taskId == mTargetTaskId) { + closingAppTarget = target; + } + } + + if (closingAppTarget == null) { + if (Log.isLoggable(TAG, Log.WARN)) { + Log.w(TAG, "No closing app target. Using stub animation."); + } + anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration())); + return anim; + } + if (recentsTarget == null) { + if (Log.isLoggable(TAG, Log.WARN)) { + Log.w(TAG, "No recents target. Using stub animation."); + } + anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration())); + return anim; + } + + View thumbnailView = mRecentsView.getThumbnailViewForTask(mTargetTaskId); + if (thumbnailView == null) { + // TODO: We should either 1) guarantee the view is loaded before attempting this + // or 2) have a backup animation. + if (Log.isLoggable(TAG, Log.WARN)) { + Log.w(TAG, "No thumbnail view for running task. Using stub animation."); + } + anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration())); + return anim; + } + + playAppScaleDownAnim(anim, closingAppTarget, recentsTarget, thumbnailView); + return anim; } /** + * Animate a closing app to scale down to the location of the thumbnail view in recents. + * + * @param anim animator set + * @param appTarget the app surface thats closing + * @param recentsTarget the surface containing recents + * @param thumbnailView the thumbnail view to animate to + */ + private void playAppScaleDownAnim(@NonNull AnimatorSet anim, + @NonNull RemoteAnimationTargetCompat appTarget, + @NonNull RemoteAnimationTargetCompat recentsTarget, @NonNull View thumbnailView) { + + // Identify where the entering remote app should animate to. + Rect endRect = new Rect(); + thumbnailView.getGlobalVisibleRect(endRect); + + Rect appBounds = appTarget.sourceContainerBounds; + + ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1); + valueAnimator.setDuration(APP_SCALE_DOWN_DURATION); + + SyncRtSurfaceTransactionApplierCompat surfaceApplier = + new SyncRtSurfaceTransactionApplierCompat(thumbnailView); + + // Keep recents visible throughout the animation. + SurfaceParams[] params = new SurfaceParams[2]; + params[0] = new SurfaceParams(recentsTarget.leash, 1f, null /* matrix */, + null /* windowCrop */, getLayer(recentsTarget, MODE_OPENING), 0 /* cornerRadius */); + + valueAnimator.addUpdateListener(new MultiValueUpdateListener() { + private final FloatProp mScaleX; + private final FloatProp mScaleY; + private final FloatProp mTranslationX; + private final FloatProp mTranslationY; + private final FloatProp mAlpha; + + { + // Scale down and move to view location. + float endScaleX = ((float) endRect.width()) / appBounds.width(); + mScaleX = new FloatProp(1f, endScaleX, 0, APP_SCALE_DOWN_DURATION, + ACCEL_DEACCEL); + float endScaleY = ((float) endRect.height()) / appBounds.height(); + mScaleY = new FloatProp(1f, endScaleY, 0, APP_SCALE_DOWN_DURATION, + ACCEL_DEACCEL); + float endTranslationX = endRect.left - + (appBounds.width() - thumbnailView.getWidth()) / 2.0f; + mTranslationX = new FloatProp(0, endTranslationX, 0, APP_SCALE_DOWN_DURATION, + ACCEL_DEACCEL); + float endTranslationY = endRect.top - + (appBounds.height() - thumbnailView.getHeight()) / 2.0f; + mTranslationY = new FloatProp(0, endTranslationY, 0, APP_SCALE_DOWN_DURATION, + ACCEL_DEACCEL); + + // Fade out quietly near the end to be replaced by the real view. + mAlpha = new FloatProp(1.0f, 0, + APP_SCALE_DOWN_DURATION - APP_TO_THUMBNAIL_FADE_DURATION, + APP_TO_THUMBNAIL_FADE_DURATION, ACCEL_2); + } + + @Override + public void onUpdate(float percent) { + Matrix m = new Matrix(); + m.setScale(mScaleX.value, mScaleY.value, + appBounds.width() / 2.0f, appBounds.height() / 2.0f); + m.postTranslate(mTranslationX.value, mTranslationY.value); + + params[1] = new SurfaceParams(appTarget.leash, mAlpha.value, m, + null /* windowCrop */, getLayer(appTarget, MODE_CLOSING), + 0 /* cornerRadius */); + surfaceApplier.scheduleApply(params); + } + }); + anim.play(valueAnimator); + } + + /** * Get duration of animation from app to overview. * * @return duration of animation */ long getRecentsLaunchDuration() { - return RECENTS_LAUNCH_DURATION; + return APP_SCALE_DOWN_DURATION; } } |