Moving some methods related to task launch animation to
recents view and related classes.
This allows the common animation to be used in fallback activity.
Bug: 75979063
Change-Id: I2b5bf5e66406621305b9a076793434f9c5cecdfd
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index f1471a7..8f2e104 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -17,7 +17,6 @@
package com.android.launcher3;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
@@ -53,7 +52,6 @@
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.shortcuts.DeepShortcutView;
@@ -93,8 +91,8 @@
private static final int CLOSING_TRANSITION_DURATION_MS = 350;
// Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down.
- private static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f;
- private static final float ALL_APPS_PROGRESS_OVERSHOOT = 0.99581414f;
+ public static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f;
+ public static final float ALL_APPS_PROGRESS_OVERSHOOT = 0.99581414f;
private final DragLayer mDragLayer;
private final Launcher mLauncher;
@@ -148,7 +146,14 @@
@Override
public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
- AnimatorSet anim = createLaunchAnimatorForView(v, targetCompats);
+ Animator[] anims = composeRecentsLaunchAnimator(v, targetCompats);
+ AnimatorSet anim = new AnimatorSet();
+ if (anims != null) {
+ anim.playTogether(anims);
+ } else {
+ anim.play(getLauncherAnimators(v, targetCompats));
+ anim.play(getWindowAnimators(v, targetCompats));
+ }
mLauncher.getStateManager().setCurrentAnimation(anim);
return anim;
}
@@ -167,19 +172,6 @@
return getDefaultActivityLaunchOptions(launcher, v);
}
- private AnimatorSet createLaunchAnimatorForView(View v, RemoteAnimationTargetCompat[] targets) {
- Animator[] anims = composeRecentsLaunchAnimator(v, new AnimConfig(targets,
- RECENTS_LAUNCH_DURATION, Interpolators.TOUCH_RESPONSE_INTERPOLATOR));
- AnimatorSet anim = new AnimatorSet();
- if (anims != null) {
- anim.playTogether(anims);
- } else {
- anim.play(getLauncherAnimators(v, targets));
- anim.play(getWindowAnimators(v, targets));
- }
- return anim;
- }
-
/**
* Try to find a TaskView that corresponds with the component of the launched view.
*
@@ -238,32 +230,21 @@
return taskView;
}
- public AnimatorSet composeUserControlledRecentsLaunchAnimator(TaskView v, AnimConfig config) {
- Animator[] anims = composeRecentsLaunchAnimator(v, config);
- AnimatorSet anim = new AnimatorSet();
- anim.playTogether(anims);
- return anim;
- }
-
/**
* Composes the animations for a launch from the recents list if possible.
*/
- private Animator[] composeRecentsLaunchAnimator(View v, AnimConfig config) {
+ private Animator[] composeRecentsLaunchAnimator(View v,
+ RemoteAnimationTargetCompat[] targets) {
// Ensure recents is actually visible
if (!mLauncher.getStateManager().getState().overviewUi) {
return null;
}
RecentsView recentsView = mLauncher.getOverviewPanel();
- boolean launcherClosing = launcherIsATargetWithMode(config.targets, MODE_CLOSING);
- if (config.userControlled) {
- // We don't pass any targets when creating a user-controlled animation. In this case,
- // assume launcher is closing.
- launcherClosing = true;
- }
+ boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING);
boolean skipLauncherChanges = !launcherClosing;
- TaskView taskView = findTaskViewToLaunch(mLauncher, v, config.targets);
+ TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets);
if (taskView == null) {
return null;
}
@@ -272,7 +253,10 @@
Animator launcherAnim;
final AnimatorListenerAdapter windowAnimEndListener;
if (launcherClosing) {
- launcherAnim = getRecentsLauncherAnimator(recentsView, taskView, config);
+ launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
+ launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
+ launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
+
// Make sure recents gets fixed up by resetting task alphas and scales, etc.
windowAnimEndListener = mReapplyStateListener;
} else {
@@ -289,150 +273,25 @@
};
}
- Animator windowAnim = getRecentsWindowAnimator(taskView, skipLauncherChanges, config);
- if (!config.userControlled) {
- // Don't reset properties if the animation is user-controlled, as we will run the
- // "real" (not user controlled) animation from where they left off when they let go.
- windowAnim.addListener(windowAnimEndListener);
- }
+ Animator windowAnim = getRecentsWindowAnimator(taskView, skipLauncherChanges, targets);
+ windowAnim.addListener(windowAnimEndListener);
return new Animator[] {launcherAnim, windowAnim};
}
/**
- * Animate adjacent tasks off screen while scaling up, and translate hotseat off screen as well.
- *
- * If launching one of the adjacent tasks, parallax the center task and other adjacent task
- * to the right.
- */
- private Animator getRecentsLauncherAnimator(RecentsView recentsView, TaskView v,
- AnimConfig config) {
- AnimatorSet launcherAnimator = new AnimatorSet();
-
- int launchedTaskIndex = recentsView.indexOfChild(v);
- int centerTaskIndex = recentsView.getCurrentPage();
- boolean launchingCenterTask = launchedTaskIndex == centerTaskIndex;
- boolean isRtl = recentsView.isRtl();
-
- RecentsAnimationInterpolator recentsInterpolator = getRecentsInterpolator(v);
- TaskWindowBounds endInterpolation = recentsInterpolator.interpolate(1);
- float toScale = endInterpolation.taskScale;
- float toTranslationY = endInterpolation.taskY;
- float displacementX = v.getWidth() * (toScale - v.getScaleX());
- if (launchingCenterTask) {
-
- if (launchedTaskIndex - 1 >= 0) {
- TaskView adjacentPage1 = (TaskView) recentsView.getPageAt(launchedTaskIndex - 1);
- ObjectAnimator adjacentTask1ScaleAndTranslate =
- LauncherAnimUtils.ofPropertyValuesHolder(adjacentPage1,
- new PropertyListBuilder()
- .scale(adjacentPage1.getScaleX() * toScale)
- .translationY(toTranslationY)
- .translationX(isRtl ? displacementX : -displacementX)
- .build());
- adjacentTask1ScaleAndTranslate.setInterpolator(config.interpolator);
- adjacentTask1ScaleAndTranslate.setDuration(config.duration);
- launcherAnimator.play(adjacentTask1ScaleAndTranslate);
- }
- if (launchedTaskIndex + 1 < recentsView.getPageCount()) {
- TaskView adjacentTask2 = (TaskView) recentsView.getPageAt(launchedTaskIndex + 1);
- ObjectAnimator adjacentTask2ScaleAndTranslate =
- LauncherAnimUtils.ofPropertyValuesHolder(adjacentTask2,
- new PropertyListBuilder()
- .scale(adjacentTask2.getScaleX() * toScale)
- .translationY(toTranslationY)
- .translationX(isRtl ? -displacementX : displacementX)
- .build());
- adjacentTask2ScaleAndTranslate.setInterpolator(config.interpolator);
- adjacentTask2ScaleAndTranslate.setDuration(config.duration);
- launcherAnimator.play(adjacentTask2ScaleAndTranslate);
- }
- } else {
- // We are launching an adjacent task, so parallax the center and other adjacent task.
- TaskView centerTask = (TaskView) recentsView.getPageAt(centerTaskIndex);
- ObjectAnimator centerTaskParallaxOffscreen =
- LauncherAnimUtils.ofPropertyValuesHolder(centerTask,
- new PropertyListBuilder()
- .translationX(isRtl ? -displacementX : displacementX)
- .build());
- centerTaskParallaxOffscreen.setInterpolator(config.interpolator);
- centerTaskParallaxOffscreen.setDuration(config.duration);
- launcherAnimator.play(centerTaskParallaxOffscreen);
- int otherAdjacentTaskIndex = centerTaskIndex + (centerTaskIndex - launchedTaskIndex);
- if (otherAdjacentTaskIndex >= 0
- && otherAdjacentTaskIndex < recentsView.getPageCount()) {
- TaskView otherAdjacentTask = (TaskView) recentsView.getPageAt(
- otherAdjacentTaskIndex);
- ObjectAnimator otherAdjacentTaskParallaxOffscreen =
- LauncherAnimUtils.ofPropertyValuesHolder(otherAdjacentTask,
- new PropertyListBuilder()
- .translationX(isRtl ? -displacementX : displacementX)
- .scale(1)
- .build());
- otherAdjacentTaskParallaxOffscreen.setInterpolator(config.interpolator);
- otherAdjacentTaskParallaxOffscreen.setDuration(config.duration);
- launcherAnimator.play(otherAdjacentTaskParallaxOffscreen);
- }
- }
-
- float allAppsProgressOffscreen = ALL_APPS_PROGRESS_OFF_SCREEN;
- LauncherState state = mLauncher.getStateManager().getState();
- if ((state.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) != 0) {
- float maxShiftRange = mDeviceProfile.heightPx;
- float currShiftRange = mLauncher.getAllAppsController().getShiftRange();
- allAppsProgressOffscreen = 1f + (maxShiftRange - currShiftRange) / maxShiftRange;
- }
- Animator allAppsSlideOut = ObjectAnimator.ofFloat(mLauncher.getAllAppsController(),
- ALL_APPS_PROGRESS, allAppsProgressOffscreen);
- allAppsSlideOut.setInterpolator(config.interpolator);
- allAppsSlideOut.setDuration(config.duration);
- launcherAnimator.play(allAppsSlideOut);
-
- Workspace workspace = mLauncher.getWorkspace();
- float[] workspaceScaleAndTranslation = NORMAL
- .getWorkspaceScaleAndTranslation(mLauncher);
- Animator recenterWorkspace = LauncherAnimUtils.ofPropertyValuesHolder(
- workspace, new PropertyListBuilder()
- .translationX(workspaceScaleAndTranslation[1])
- .translationY(workspaceScaleAndTranslation[2])
- .build());
- recenterWorkspace.setInterpolator(config.interpolator);
- recenterWorkspace.setDuration(config.duration);
- launcherAnimator.play(recenterWorkspace);
- CellLayout currentWorkspacePage = (CellLayout) workspace.getPageAt(
- workspace.getCurrentPage());
-
- return launcherAnimator;
- }
-
- private RecentsAnimationInterpolator getRecentsInterpolator(TaskView v) {
- Rect taskViewBounds = new Rect();
- mDragLayer.getDescendantRectRelativeToSelf(v, taskViewBounds);
-
- // TODO: Use the actual target insets instead of the current thumbnail insets in case the
- // device state has changed
- return new RecentsAnimationInterpolator(
- new Rect(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx),
- v.getThumbnail().getInsets(),
- taskViewBounds,
- new Rect(0, v.getThumbnail().getTop(), 0, 0),
- v.getScaleX(),
- v.getTranslationX());
- }
-
- /**
* @return Animator that controls the window of the opening targets for the recents launch
* animation.
*/
private ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipLauncherChanges,
- AnimConfig config) {
- final RecentsAnimationInterpolator recentsInterpolator = getRecentsInterpolator(v);
+ RemoteAnimationTargetCompat[] targets) {
+ final RecentsAnimationInterpolator recentsInterpolator = v.getRecentsInterpolator();
Rect crop = new Rect();
Matrix matrix = new Matrix();
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
- appAnimator.setDuration(config.duration);
- appAnimator.setInterpolator(config.interpolator);
+ appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
+ appAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
appAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
boolean isFirstFrame = true;
@@ -454,11 +313,9 @@
v.setScaleY(tw.taskScale);
v.setTranslationX(tw.taskX);
v.setTranslationY(tw.taskY);
- if (!config.userControlled) {
- // Defer fading out the view until after the app window gets faded in
- v.setAlpha(getValue(1f, 0f, alphaDuration, alphaDuration,
- appAnimator.getDuration() * percent, Interpolators.LINEAR));
- }
+ // Defer fading out the view until after the app window gets faded in
+ v.setAlpha(getValue(1f, 0f, alphaDuration, alphaDuration,
+ appAnimator.getDuration() * percent, Interpolators.LINEAR));
}
matrix.setScale(tw.winScale, tw.winScale);
@@ -470,7 +327,7 @@
appAnimator.getDuration() * percent, Interpolators.LINEAR);
TransactionCompat t = new TransactionCompat();
- for (RemoteAnimationTargetCompat target : config.targets) {
+ for (RemoteAnimationTargetCompat target : targets) {
if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) {
t.setAlpha(target.leash, alpha);
@@ -967,24 +824,4 @@
newPercent = i.getInterpolation(newPercent);
return end * newPercent + start * (1 - newPercent);
}
-
- public static class AnimConfig {
- public RemoteAnimationTargetCompat[] targets;
- public long duration;
- public Interpolator interpolator;
-
- public boolean userControlled = false;
-
- public AnimConfig(RemoteAnimationTargetCompat[] targets, long duration,
- Interpolator interpolator) {
- this.targets = targets;
- this.duration = duration;
- this.interpolator = interpolator;
- }
-
- public AnimConfig(long duration, Interpolator interpolator) {
- this(new RemoteAnimationTargetCompat[0], duration, interpolator);
- userControlled = true;
- }
- }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index dca0018..369ae3a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -20,7 +20,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.util.Log;
import android.view.MotionEvent;
@@ -28,8 +27,6 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppTransitionManagerImpl;
-import com.android.launcher3.LauncherAppTransitionManagerImpl.AnimConfig;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
@@ -166,21 +163,20 @@
if (goingUp) {
mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged,
true /* animateTaskView */, true /* removeTask */, maxDuration);
- mCurrentAnimation = AnimatorPlaybackController
- .wrap(mPendingAnimation.anim, maxDuration);
+
mEndDisplacement = -mTaskBeingDragged.getHeight();
} else {
- LauncherAppTransitionManagerImpl appTransitionManager =
- (LauncherAppTransitionManagerImpl) mLauncher.getAppTransitionManager();
- AnimatorSet anim = appTransitionManager.composeUserControlledRecentsLaunchAnimator(
- mTaskBeingDragged, new AnimConfig(maxDuration, Interpolators.ZOOM_IN));
- mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration);
+ mPendingAnimation = mRecentsView.createTaskLauncherAnimation(
+ mTaskBeingDragged, maxDuration);
+ mPendingAnimation.anim.setInterpolator(Interpolators.ZOOM_IN);
mTempCords[1] = mTaskBeingDragged.getHeight();
dl.getDescendantCoordRelativeToSelf(mTaskBeingDragged, mTempCords);
mEndDisplacement = dl.getHeight() - mTempCords[1];
}
+ mCurrentAnimation = AnimatorPlaybackController
+ .wrap(mPendingAnimation.anim, maxDuration);
mCurrentAnimation.getTarget().addListener(this);
mCurrentAnimation.dispatchOnStart();
mProgressMultiplier = 1 / mEndDisplacement;
@@ -258,7 +254,6 @@
}
if (wasSuccess) {
if (!mCurrentAnimationIsGoingUp) {
- mTaskBeingDragged.launchTask(false);
mLauncher.getUserEventDispatcher().logTaskLaunch(logAction,
Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent());
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index ad0e253..d428f23 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -15,8 +15,14 @@
*/
package com.android.quickstep.views;
+import static com.android.launcher3.LauncherAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
+import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
@@ -30,6 +36,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
/**
@@ -137,4 +144,23 @@
// Lazily update the empty message only when the task stack is reapplied
updateEmptyMessage();
}
+
+ /**
+ * Animates adjacent tasks and translate hotseat off screen as well.
+ */
+ @Override
+ public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) {
+ AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv);
+
+ float allAppsProgressOffscreen = ALL_APPS_PROGRESS_OFF_SCREEN;
+ LauncherState state = mActivity.getStateManager().getState();
+ if ((state.getVisibleElements(mActivity) & ALL_APPS_HEADER_EXTRA) != 0) {
+ float maxShiftRange = mActivity.getDeviceProfile().heightPx;
+ float currShiftRange = mActivity.getAllAppsController().getShiftRange();
+ allAppsProgressOffscreen = 1f + (maxShiftRange - currShiftRange) / maxShiftRange;
+ }
+ anim.play(ObjectAnimator.ofFloat(
+ mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen));
+ return anim;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7a5fd2f..bac8fc7 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -55,10 +55,13 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.Themes;
import com.android.quickstep.PendingAnimation;
import com.android.quickstep.QuickScrubController;
+import com.android.quickstep.RecentsAnimationInterpolator;
+import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds;
import com.android.quickstep.RecentsModel;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.shared.recents.model.RecentsTaskLoader;
@@ -839,4 +842,94 @@
canvas.restore();
}
}
+
+ /**
+ * Animate adjacent tasks off screen while scaling up.
+ *
+ * If launching one of the adjacent tasks, parallax the center task and other adjacent task
+ * to the right.
+ */
+ public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) {
+ AnimatorSet anim = new AnimatorSet();
+
+ int taskIndex = indexOfChild(tv);
+ int centerTaskIndex = getCurrentPage();
+ boolean launchingCenterTask = taskIndex == centerTaskIndex;
+
+ TaskWindowBounds endInterpolation = tv.getRecentsInterpolator().interpolate(1);
+ float toScale = endInterpolation.taskScale;
+ float toTranslationY = endInterpolation.taskY;
+
+ float displacementX = tv.getWidth() * (toScale - tv.getScaleX());
+ if (launchingCenterTask) {
+ if (taskIndex - 1 >= 0) {
+ anim.play(createAnimForChild(
+ taskIndex - 1, toScale, displacementX, toTranslationY));
+ }
+ if (taskIndex + 1 < getPageCount()) {
+ anim.play(createAnimForChild(
+ taskIndex + 1, toScale, -displacementX, toTranslationY));
+ }
+ } else {
+ // We are launching an adjacent task, so parallax the center and other adjacent task.
+ anim.play(ObjectAnimator.ofFloat(getPageAt(centerTaskIndex), TRANSLATION_X,
+ mIsRtl ? -displacementX : displacementX));
+
+ int otherAdjacentTaskIndex = centerTaskIndex + (centerTaskIndex - taskIndex);
+ if (otherAdjacentTaskIndex >= 0 && otherAdjacentTaskIndex < getPageCount()) {
+ anim.play(ObjectAnimator.ofPropertyValuesHolder(getPageAt(otherAdjacentTaskIndex),
+ new PropertyListBuilder()
+ .translationX(mIsRtl ? -displacementX : displacementX)
+ .scale(1)
+ .build()));
+ }
+ }
+ return anim;
+ }
+
+ private ObjectAnimator createAnimForChild(int childIndex, float toScale, float tx, float ty) {
+ View child = getChildAt(childIndex);
+ return ObjectAnimator.ofPropertyValuesHolder(child,
+ new PropertyListBuilder()
+ .scale(child.getScaleX() * toScale)
+ .translationY(ty)
+ .translationX(mIsRtl ? tx : -tx)
+ .build());
+ }
+
+ public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {
+ if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
+ throw new IllegalStateException("Another pending animation is still running");
+ }
+ AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv);
+
+ int count = getChildCount();
+ if (count == 0) {
+ return new PendingAnimation(anim);
+ }
+
+ final RecentsAnimationInterpolator recentsInterpolator = tv.getRecentsInterpolator();
+ ValueAnimator targetViewAnim = ValueAnimator.ofFloat(0, 1);
+ targetViewAnim.addUpdateListener((animation) -> {
+ float percent = animation.getAnimatedFraction();
+ TaskWindowBounds tw = recentsInterpolator.interpolate(percent);
+ tv.setScaleX(tw.taskScale);
+ tv.setScaleY(tw.taskScale);
+ tv.setTranslationX(tw.taskX);
+ tv.setTranslationY(tw.taskY);
+ });
+ anim.play(targetViewAnim);
+ anim.setDuration(duration);
+
+ mPendingAnimation = new PendingAnimation(anim);
+ mPendingAnimation.addEndListener((isSuccess) -> {
+ if (isSuccess) {
+ tv.launchTask(false);
+ } else {
+ resetTaskVisuals();
+ }
+ mPendingAnimation = null;
+ });
+ return mPendingAnimation;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 9884a48..a701862 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
+import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
@@ -29,7 +30,9 @@
import android.widget.ImageView;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.quickstep.RecentsAnimationInterpolator;
import com.android.quickstep.views.RecentsView.PageCallbacks;
import com.android.quickstep.views.RecentsView.ScrollState;
import com.android.systemui.shared.recents.model.Task;
@@ -183,6 +186,23 @@
return false;
}
+ public RecentsAnimationInterpolator getRecentsInterpolator() {
+ Rect taskViewBounds = new Rect();
+ BaseDraggingActivity activity = BaseDraggingActivity.fromContext(getContext());
+ DeviceProfile dp = activity.getDeviceProfile();
+ activity.getDragLayer().getDescendantRectRelativeToSelf(this, taskViewBounds);
+
+ // TODO: Use the actual target insets instead of the current thumbnail insets in case the
+ // device state has changed
+ return new RecentsAnimationInterpolator(
+ new Rect(0, 0, dp.widthPx, dp.heightPx),
+ getThumbnail().getInsets(),
+ taskViewBounds,
+ new Rect(0, getThumbnail().getTop(), 0, 0),
+ getScaleX(),
+ getTranslationX());
+ }
+
private static final class TaskOutlineProvider extends ViewOutlineProvider {
private final int mMarginTop;
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 6fea201..087752d 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -18,6 +18,7 @@
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
+import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import java.util.ArrayList;
@@ -184,10 +185,14 @@
private void getAnimationsRecur(AnimatorSet anim, ArrayList<ValueAnimator> out) {
long forceDuration = anim.getDuration();
+ TimeInterpolator forceInterpolator = anim.getInterpolator();
for (Animator child : anim.getChildAnimations()) {
if (forceDuration > 0) {
child.setDuration(forceDuration);
}
+ if (forceInterpolator != null) {
+ child.setInterpolator(forceInterpolator);
+ }
if (child instanceof ValueAnimator) {
out.add((ValueAnimator) child);
} else if (child instanceof AnimatorSet) {