From 3a6746ac04e8564d1e5d244ae855a1ecb1a68105 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Thu, 29 Mar 2018 09:39:56 -0700 Subject: [PATCH] Animate TaskView as you swipe down on it to launch Bug: 73835352 Change-Id: Ia255a7af8fb6cd972f99de6390e097afc29c1b90 --- .../LauncherAppTransitionManagerImpl.java | 106 +++++++++++++----- .../uioverrides/TaskViewTouchController.java | 9 +- .../quickstep/views/LauncherRecentsView.java | 7 +- src/com/android/launcher3/Launcher.java | 4 + .../anim/AnimatorPlaybackController.java | 1 - 5 files changed, 92 insertions(+), 35 deletions(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index ab4dae8297..f1471a7d52 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -148,14 +148,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag @Override public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] 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)); - } + AnimatorSet anim = createLaunchAnimatorForView(v, targetCompats); mLauncher.getStateManager().setCurrentAnimation(anim); return anim; } @@ -174,6 +167,19 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag 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. * @@ -232,21 +238,32 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag 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, - RemoteAnimationTargetCompat[] targets) { + private Animator[] composeRecentsLaunchAnimator(View v, AnimConfig config) { // Ensure recents is actually visible if (!mLauncher.getStateManager().getState().overviewUi) { return null; } RecentsView recentsView = mLauncher.getOverviewPanel(); - boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING); + 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 skipLauncherChanges = !launcherClosing; - TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets); + TaskView taskView = findTaskViewToLaunch(mLauncher, v, config.targets); if (taskView == null) { return null; } @@ -255,7 +272,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag Animator launcherAnim; final AnimatorListenerAdapter windowAnimEndListener; if (launcherClosing) { - launcherAnim = getRecentsLauncherAnimator(recentsView, taskView); + launcherAnim = getRecentsLauncherAnimator(recentsView, taskView, config); // Make sure recents gets fixed up by resetting task alphas and scales, etc. windowAnimEndListener = mReapplyStateListener; } else { @@ -272,8 +289,12 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag }; } - Animator windowAnim = getRecentsWindowAnimator(taskView, skipLauncherChanges, targets); - windowAnim.addListener(windowAnimEndListener); + 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); + } return new Animator[] {launcherAnim, windowAnim}; } @@ -283,7 +304,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag * 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) { + private Animator getRecentsLauncherAnimator(RecentsView recentsView, TaskView v, + AnimConfig config) { AnimatorSet launcherAnimator = new AnimatorSet(); int launchedTaskIndex = recentsView.indexOfChild(v); @@ -307,6 +329,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag .translationY(toTranslationY) .translationX(isRtl ? displacementX : -displacementX) .build()); + adjacentTask1ScaleAndTranslate.setInterpolator(config.interpolator); + adjacentTask1ScaleAndTranslate.setDuration(config.duration); launcherAnimator.play(adjacentTask1ScaleAndTranslate); } if (launchedTaskIndex + 1 < recentsView.getPageCount()) { @@ -318,6 +342,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag .translationY(toTranslationY) .translationX(isRtl ? -displacementX : displacementX) .build()); + adjacentTask2ScaleAndTranslate.setInterpolator(config.interpolator); + adjacentTask2ScaleAndTranslate.setDuration(config.duration); launcherAnimator.play(adjacentTask2ScaleAndTranslate); } } else { @@ -328,6 +354,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag 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 @@ -340,6 +368,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag .translationX(isRtl ? -displacementX : displacementX) .scale(1) .build()); + otherAdjacentTaskParallaxOffscreen.setInterpolator(config.interpolator); + otherAdjacentTaskParallaxOffscreen.setDuration(config.duration); launcherAnimator.play(otherAdjacentTaskParallaxOffscreen); } } @@ -353,6 +383,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } 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(); @@ -363,12 +395,12 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag .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()); - launcherAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); - launcherAnimator.setDuration(RECENTS_LAUNCH_DURATION); return launcherAnimator; } @@ -392,15 +424,15 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag * animation. */ private ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipLauncherChanges, - RemoteAnimationTargetCompat[] targets) { + AnimConfig config) { final RecentsAnimationInterpolator recentsInterpolator = getRecentsInterpolator(v); Rect crop = new Rect(); Matrix matrix = new Matrix(); ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); - appAnimator.setDuration(RECENTS_LAUNCH_DURATION); - appAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); + appAnimator.setDuration(config.duration); + appAnimator.setInterpolator(config.interpolator); appAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { boolean isFirstFrame = true; @@ -416,14 +448,17 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag final float percent = animation.getAnimatedFraction(); TaskWindowBounds tw = recentsInterpolator.interpolate(percent); + float alphaDuration = 75; if (!skipLauncherChanges) { v.setScaleX(tw.taskScale); v.setScaleY(tw.taskScale); v.setTranslationX(tw.taskX); v.setTranslationY(tw.taskY); - // Defer fading out the view until after the app window gets faded in - v.setAlpha(getValue(1f, 0f, 75, 75, - appAnimator.getDuration() * percent, Interpolators.LINEAR)); + 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)); + } } matrix.setScale(tw.winScale, tw.winScale); @@ -431,12 +466,11 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag crop.set(tw.winCrop); // Fade in the app window. - float alphaDuration = 75; float alpha = getValue(0f, 1f, 0, alphaDuration, appAnimator.getDuration() * percent, Interpolators.LINEAR); TransactionCompat t = new TransactionCompat(); - for (RemoteAnimationTargetCompat target : targets) { + for (RemoteAnimationTargetCompat target : config.targets) { if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) { t.setAlpha(target.leash, alpha); @@ -933,4 +967,24 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag 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 d11547de84..dca0018ece 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java @@ -28,8 +28,11 @@ import android.view.View; 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; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.touch.SwipeDetector; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; @@ -167,8 +170,10 @@ public class TaskViewTouchController extends AnimatorListenerAdapter .wrap(mPendingAnimation.anim, maxDuration); mEndDisplacement = -mTaskBeingDragged.getHeight(); } else { - AnimatorSet anim = new AnimatorSet(); - // TODO: Setup a zoom animation + LauncherAppTransitionManagerImpl appTransitionManager = + (LauncherAppTransitionManagerImpl) mLauncher.getAppTransitionManager(); + AnimatorSet anim = appTransitionManager.composeUserControlledRecentsLaunchAnimator( + mTaskBeingDragged, new AnimConfig(maxDuration, Interpolators.ZOOM_IN)); mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration); mTempCords[1] = mTaskBeingDragged.getHeight(); diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 55ed9a941e..ad0e2530c2 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -26,7 +26,6 @@ import android.util.AttributeSet; import android.util.FloatProperty; import android.view.View; import android.view.ViewDebug; -import android.widget.FrameLayout; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; @@ -92,11 +91,7 @@ public class LauncherRecentsView extends RecentsView implements Insett mInsets.set(insets); DeviceProfile dp = mActivity.getDeviceProfile(); Rect padding = getPadding(dp, getContext()); - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); - lp.bottomMargin = padding.bottom; - setLayoutParams(lp); - - setPadding(padding.left, padding.top, padding.right, 0); + setPadding(padding.left, padding.top, padding.right, padding.bottom); mPagePadding.set(padding); mPagePadding.top += getResources().getDimensionPixelSize(R.dimen.task_thumbnail_top_margin); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 11e8c5712a..50a88ce9ed 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1684,6 +1684,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L : mAppTransitionManager.getActivityLaunchOptions(this, v); } + public LauncherAppTransitionManager getAppTransitionManager() { + return mAppTransitionManager; + } + @TargetApi(Build.VERSION_CODES.M) @Override protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) { diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java index 68e98479b0..6fea201564 100644 --- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java +++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java @@ -206,7 +206,6 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat anim.setCurrentPlayTime(Math.min(playPos, anim.getDuration())); } } - } private class OnAnimationEndDispatcher extends AnimationSuccessListener {