diff options
-rw-r--r-- | go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java | 107 | ||||
-rw-r--r-- | go/quickstep/src/com/android/quickstep/views/IconRecentsView.java | 103 |
2 files changed, 106 insertions, 104 deletions
diff --git a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java index c228bb94f..2dc25546d 100644 --- a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java +++ b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java @@ -15,30 +15,21 @@ */ 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.quickstep.views.IconRecentsView.REMOTE_APP_TO_OVERVIEW_DURATION; 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.util.RemoteAnimationTargetSet; 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. @@ -47,9 +38,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat. */ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements RemoteAnimationProvider { - - 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; @@ -131,106 +119,17 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple return anim; } - View thumbnailView = mRecentsView.getBottomThumbnailView(); - if (thumbnailView == null) { - // This can be null if there were previously 0 tasks and the recycler view has not had - // enough time to take in the data change, bind a new view, and lay out the new view. - // TODO: Have a fallback to animate to - 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); + mRecentsView.playAppScaleDownAnim(anim, closingAppTarget, recentsTarget); 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]; - // Closing app should stay on top. - int boostedMode = MODE_CLOSING; - params[0] = new SurfaceParams(recentsTarget.leash, 1f, null /* matrix */, - null /* windowCrop */, getLayer(recentsTarget, boostedMode), 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, boostedMode), - 0 /* cornerRadius */); - surfaceApplier.scheduleApply(params); - } - }); - anim.play(valueAnimator); - } - - /** * Get duration of animation from app to overview. * * @return duration of animation */ long getRecentsLaunchDuration() { - return APP_SCALE_DOWN_DURATION; + return REMOTE_APP_TO_OVERVIEW_DURATION; } } diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java index c69e53458..89d248cd3 100644 --- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java +++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java @@ -19,10 +19,14 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static androidx.recyclerview.widget.LinearLayoutManager.VERTICAL; +import static com.android.launcher3.anim.Interpolators.ACCEL_2; +import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.quickstep.TaskAdapter.CHANGE_EVENT_TYPE_EMPTY_TO_CONTENT; import static com.android.quickstep.TaskAdapter.ITEM_TYPE_CLEAR_ALL; import static com.android.quickstep.TaskAdapter.ITEM_TYPE_TASK; import static com.android.quickstep.TaskAdapter.TASKS_START_POSITION; +import static com.android.quickstep.util.RemoteAnimationProvider.getLayer; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -32,6 +36,7 @@ import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Resources; +import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.ArraySet; @@ -64,7 +69,11 @@ import com.android.quickstep.TaskAdapter; import com.android.quickstep.TaskHolder; import com.android.quickstep.TaskListLoader; import com.android.quickstep.TaskSwipeCallback; +import com.android.quickstep.util.MultiValueUpdateListener; import com.android.systemui.shared.recents.model.Task; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import java.util.ArrayList; import java.util.List; @@ -102,6 +111,11 @@ public final class IconRecentsView extends FrameLayout implements Insettable { private static final float ITEM_ANIMATE_OUT_TRANSLATION_X_RATIO = .25f; private static final long CLEAR_ALL_FADE_DELAY = 120; + private static final long APP_TO_THUMBNAIL_FADE_DURATION = 50; + private static final long APP_SCALE_DOWN_DURATION = 400; + + public static final long REMOTE_APP_TO_OVERVIEW_DURATION = APP_SCALE_DOWN_DURATION; + /** * A ratio representing the view's relative placement within its padded space. For example, 0 * is top aligned and 0.5 is centered vertically. @@ -565,6 +579,95 @@ public final class IconRecentsView extends FrameLayout implements Insettable { mLayoutAnimation.start(); } + /** + * 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 + */ + public void playAppScaleDownAnim(@NonNull AnimatorSet anim, + @NonNull RemoteAnimationTargetCompat appTarget, + @NonNull RemoteAnimationTargetCompat recentsTarget) { + + View thumbnailView = getBottomThumbnailView(); + + if (thumbnailView == null) { + // This can be null if there were previously 0 tasks and the recycler view has not had + // enough time to take in the data change, bind a new view, and lay out the new view. + // TODO: Have a fallback to animate to + anim.play(ValueAnimator.ofInt(0, 1).setDuration(REMOTE_APP_TO_OVERVIEW_DURATION)); + } + + // 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]; + // Closing app should stay on top. + int boostedMode = MODE_CLOSING; + params[0] = new SurfaceParams(recentsTarget.leash, 1f, null /* matrix */, + null /* windowCrop */, getLayer(recentsTarget, boostedMode), 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, boostedMode), + 0 /* cornerRadius */); + surfaceApplier.scheduleApply(params); + } + }); + anim.play(valueAnimator); + } + + public long getAppToOverviewAnimationDuration() { + return APP_SCALE_DOWN_DURATION; + } + @Override public void setInsets(Rect insets) { mInsets = insets; |