Loading quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +36 −194 Original line number Diff line number Diff line Loading @@ -19,6 +19,13 @@ package com.android.launcher3; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT; import static com.android.launcher3.anim.Interpolators.APP_CLOSE_ALPHA; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.TaskUtils.findTaskViewToLaunch; import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber; import static com.android.systemui.shared.recents.utilities.Utilities.getSurface; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; Loading @@ -31,7 +38,6 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.ActivityOptions; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; Loading @@ -45,7 +51,6 @@ import android.util.Log; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.InsettableFrameLayout.LayoutParams; Loading @@ -55,12 +60,10 @@ import com.android.launcher3.anim.Interpolators; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.quickstep.RecentsAnimationInterpolator; import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; Loading @@ -79,7 +82,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag implements OnDeviceProfileChangeListener { private static final String TAG = "LauncherTransition"; private static final int STATUS_BAR_TRANSITION_DURATION = 120; public static final int STATUS_BAR_TRANSITION_DURATION = 120; private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION = "android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"; Loading @@ -87,7 +90,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag private static final int APP_LAUNCH_DURATION = 500; // Use a shorter duration for x or y translation to create a curve effect private static final int APP_LAUNCH_CURVED_DURATION = 233; private static final int RECENTS_LAUNCH_DURATION = 336; public static final int RECENTS_LAUNCH_DURATION = 336; private static final int LAUNCHER_RESUME_START_DELAY = 100; private static final int CLOSING_TRANSITION_DURATION_MS = 350; Loading Loading @@ -184,64 +187,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag mRemoteAnimationProvider = animationProvider; } /** * Try to find a TaskView that corresponds with the component of the launched view. * * If this method returns a non-null TaskView, it will be used in composeRecentsLaunchAnimation. * Otherwise, we will assume we are using a normal app transition, but it's possible that the * opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView. */ private TaskView findTaskViewToLaunch( BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) { if (v instanceof TaskView) { return (TaskView) v; } RecentsView recentsView = activity.getOverviewPanel(); // It's possible that the launched view can still be resolved to a visible task view, check // the task id of the opening task and see if we can find a match. if (v.getTag() instanceof ItemInfo) { ItemInfo itemInfo = (ItemInfo) v.getTag(); ComponentName componentName = itemInfo.getTargetComponent(); if (componentName != null) { for (int i = 0; i < recentsView.getChildCount(); i++) { TaskView taskView = (TaskView) recentsView.getPageAt(i); if (recentsView.isTaskViewVisible(taskView)) { Task task = taskView.getTask(); if (componentName.equals(task.key.getComponent())) { return taskView; } } } } } if (targets == null) { return null; } // Resolve the opening task id int openingTaskId = -1; for (RemoteAnimationTargetCompat target : targets) { if (target.mode == MODE_OPENING) { openingTaskId = target.taskId; break; } } // If there is no opening task id, fall back to the normal app icon launch animation if (openingTaskId == -1) { return null; } // If the opening task id is not currently visible in overview, then fall back to normal app // icon launch animation TaskView taskView = recentsView.getTaskView(openingTaskId); if (taskView == null || !recentsView.isTaskViewVisible(taskView)) { return null; } return taskView; } /** * Composes the animations for a launch from the recents list if possible. */ Loading Loading @@ -285,7 +230,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag }; } target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets)); target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets) .setDuration(RECENTS_LAUNCH_DURATION)); target.play(launcherAnim); // Set the current animation first, before adding windowAnimEndListener. Setting current Loading @@ -296,83 +242,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag return true; } /** * @return Animator that controls the window of the opening targets for the recents launch * animation. */ private ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipLauncherChanges, RemoteAnimationTargetCompat[] targets) { final RecentsAnimationInterpolator recentsInterpolator = v.getRecentsInterpolator(); 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.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { boolean isFirstFrame = true; @Override public void onAnimationUpdate(ValueAnimator animation) { final Surface surface = getSurface(v); final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1; if (frameNumber == -1) { // Booo, not cool! Our surface got destroyed, so no reason to animate anything. Log.w(TAG, "Failed to animate, surface got destroyed."); return; } 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, alphaDuration, alphaDuration, appAnimator.getDuration() * percent, Interpolators.LINEAR)); } matrix.setScale(tw.winScale, tw.winScale); matrix.postTranslate(tw.winX, tw.winY); crop.set(tw.winCrop); // Fade in the app window. float alpha = getValue(0f, 1f, 0, alphaDuration, appAnimator.getDuration() * percent, Interpolators.LINEAR); TransactionCompat t = new TransactionCompat(); for (RemoteAnimationTargetCompat target : targets) { if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) { t.setAlpha(target.leash, alpha); // TODO: This isn't correct at the beginning of the animation, but better // than nothing. matrix.postTranslate(target.position.x, target.position.y); t.setMatrix(target.leash, matrix); t.setWindowCrop(target.leash, crop); if (!skipLauncherChanges) { t.deferTransactionUntil(target.leash, surface, frameNumber); } } if (isFirstFrame) { t.show(target.leash); } } t.setEarlyWakeup(); t.apply(); matrix.reset(); isFirstFrame = false; } }); return appAnimator; } /** * Content is everything on screen except the background and the floating view (if any). * Loading @@ -399,9 +268,9 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas); alpha.setDuration(217); alpha.setInterpolator(Interpolators.LINEAR); alpha.setInterpolator(LINEAR); ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, trans); transY.setInterpolator(Interpolators.AGGRESSIVE_EASE); transY.setInterpolator(AGGRESSIVE_EASE); transY.setDuration(350); launcherAnimator.play(alpha); Loading @@ -420,10 +289,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, alphas); dragLayerAlpha.setDuration(217); dragLayerAlpha.setInterpolator(Interpolators.LINEAR); dragLayerAlpha.setInterpolator(LINEAR); ObjectAnimator dragLayerTransY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y, trans); dragLayerTransY.setInterpolator(Interpolators.AGGRESSIVE_EASE); dragLayerTransY.setInterpolator(AGGRESSIVE_EASE); dragLayerTransY.setDuration(350); launcherAnimator.play(dragLayerAlpha); Loading Loading @@ -515,8 +384,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag boolean isBelowCenterY = lp.topMargin < centerY; x.setDuration(isBelowCenterY ? APP_LAUNCH_DURATION : APP_LAUNCH_CURVED_DURATION); y.setDuration(isBelowCenterY ? APP_LAUNCH_CURVED_DURATION : APP_LAUNCH_DURATION); x.setInterpolator(Interpolators.AGGRESSIVE_EASE); y.setInterpolator(Interpolators.AGGRESSIVE_EASE); x.setInterpolator(AGGRESSIVE_EASE); y.setInterpolator(AGGRESSIVE_EASE); appIconAnimatorSet.play(x); appIconAnimatorSet.play(y); Loading @@ -534,7 +403,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator alpha = ObjectAnimator.ofFloat(mFloatingView, View.ALPHA, 1f, 0f); alpha.setStartDelay(32); alpha.setDuration(50); alpha.setInterpolator(Interpolators.LINEAR); alpha.setInterpolator(LINEAR); appIconAnimatorSet.play(alpha); appIconAnimatorSet.addListener(new AnimatorListenerAdapter() { Loading Loading @@ -569,11 +438,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setDuration(APP_LAUNCH_DURATION); appAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { appAnimator.addUpdateListener(new MultiValueUpdateListener() { // Fade alpha for the app window. FloatProp mAlpha = new FloatProp(0f, 1f, 0, 60, LINEAR); boolean isFirstFrame = true; @Override public void onAnimationUpdate(ValueAnimator animation) { public void onUpdate(float percent) { final Surface surface = getSurface(mFloatingView); final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1; if (frameNumber == -1) { Loading @@ -581,8 +453,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag Log.w(TAG, "Failed to animate, surface got destroyed."); return; } final float percent = animation.getAnimatedFraction(); final float easePercent = Interpolators.AGGRESSIVE_EASE.getInterpolation(percent); final float easePercent = AGGRESSIVE_EASE.getInterpolation(percent); // Calculate app icon size. float iconWidth = bounds.width() * mFloatingView.getScaleX(); Loading @@ -607,11 +478,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float transY0 = floatingViewBounds[1] - offsetY; matrix.postTranslate(transX0, transY0); // Fade in the app window. float alphaDuration = 60; float alpha = getValue(0f, 1f, 0, alphaDuration, appAnimator.getDuration() * percent, Interpolators.LINEAR); // Animate the window crop so that it starts off as a square, and then reveals // horizontally. float cropHeight = deviceHeight * easePercent + deviceWidth * (1 - easePercent); Loading @@ -624,7 +490,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag TransactionCompat t = new TransactionCompat(); for (RemoteAnimationTargetCompat target : targets) { if (target.mode == MODE_OPENING) { t.setAlpha(target.leash, alpha); t.setAlpha(target.leash, mAlpha.value); // TODO: This isn't correct at the beginning of the animation, but better // than nothing. Loading Loading @@ -670,13 +536,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) { int launcherTaskId = mLauncher.getTaskId(); for (RemoteAnimationTargetCompat target : targets) { if (target.mode == mode && target.taskId == launcherTaskId) { return true; } } return false; return taskIsATargetWithMode(targets, mLauncher.getTaskId(), mode); } /** Loading Loading @@ -730,30 +590,23 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1); closingAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS); closingAnimator.addUpdateListener(new MultiValueUpdateListener() { FloatProp mDx = new FloatProp(0, endX, 0, 350, AGGRESSIVE_EASE_IN_OUT); FloatProp mScale = new FloatProp(1f, 0.8f, 0, 267, AGGRESSIVE_EASE); FloatProp mAlpha = new FloatProp(1f, 0f, 0, 350, APP_CLOSE_ALPHA); closingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { boolean isFirstFrame = true; @Override public void onAnimationUpdate(ValueAnimator animation) { final float percent = animation.getAnimatedFraction(); float currentPlayTime = percent * closingAnimator.getDuration(); float scale = getValue(1f, 0.8f, 0, 267, currentPlayTime, Interpolators.AGGRESSIVE_EASE); float dX = getValue(0, endX, 0, 350, currentPlayTime, Interpolators.AGGRESSIVE_EASE_IN_OUT); public void onUpdate(float percent) { TransactionCompat t = new TransactionCompat(); for (RemoteAnimationTargetCompat app : targets) { if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) { t.setAlpha(app.leash, getValue(1f, 0f, 0, 350, currentPlayTime, Interpolators.APP_CLOSE_ALPHA)); matrix.setScale(scale, scale, t.setAlpha(app.leash, mAlpha.value); matrix.setScale(mScale.value, mScale.value, app.sourceContainerBounds.centerX(), app.sourceContainerBounds.centerY()); matrix.postTranslate(dX, 0); matrix.postTranslate(mDx.value, 0); matrix.postTranslate(app.position.x, app.position.y); t.setMatrix(app.leash, matrix); } Loading @@ -772,6 +625,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag isFirstFrame = false; } }); return closingAnimator; } Loading Loading @@ -832,16 +686,4 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION) == PackageManager.PERMISSION_GRANTED; } /** * Helper method that allows us to get interpolated values for embedded * animations with a delay and/or different duration. */ private static float getValue(float start, float end, float delay, float duration, float currentPlayTime, Interpolator i) { float time = Math.max(0, currentPlayTime - delay); float newPercent = Math.min(1f, time / duration); newPercent = i.getInterpolation(newPercent); return end * newPercent + start * (1 - newPercent); } } quickstep/src/com/android/quickstep/RecentsActivity.java +63 −2 Original line number Diff line number Diff line Loading @@ -15,16 +15,29 @@ */ package com.android.quickstep; import static com.android.launcher3.LauncherAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.LauncherAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION; import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.app.ActivityOptions; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.View; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAnimationRunner; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.util.SystemUiController; Loading @@ -32,12 +45,18 @@ import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.fallback.RecentsRootView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; /** * A simple activity to show the recently launched tasks */ public class RecentsActivity extends BaseDraggingActivity { private Handler mUiHandler = new Handler(Looper.getMainLooper()); private RecentsRootView mRecentsRootView; private FallbackRecentsView mFallbackRecentsView; Loading Loading @@ -84,10 +103,51 @@ public class RecentsActivity extends BaseDraggingActivity { } @Override public ActivityOptions getActivityLaunchOptions(View v, boolean useDefaultLaunchOptions) { public ActivityOptions getActivityLaunchOptions(final View v, boolean useDefaultLaunchOptions) { if (useDefaultLaunchOptions || !(v instanceof TaskView)) { return null; } final TaskView taskView = (TaskView) v; RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler) { @Override public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) { return composeRecentsLaunchAnimator(taskView, targetCompats); } }; return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( runner, RECENTS_LAUNCH_DURATION, RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION)); } /** * Composes the animations for a launch from the recents list if possible. */ private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView, RemoteAnimationTargetCompat[] targets) { AnimatorSet target = new AnimatorSet(); boolean activityClosing = taskIsATargetWithMode(targets, getTaskId(), MODE_CLOSING); target.play(getRecentsWindowAnimator(taskView, !activityClosing, targets) .setDuration(RECENTS_LAUNCH_DURATION)); // Found a visible recents task that matches the opening app, lets launch the app from there if (activityClosing) { Animator adjacentAnimation = mFallbackRecentsView .createAdjacentPageAnimForTaskLaunch(taskView); adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION); adjacentAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mFallbackRecentsView.resetTaskVisuals(); } }); target.play(adjacentAnimation); } return target; } @Override public void invalidateParent(ItemInfo info) { } Loading @@ -95,6 +155,7 @@ public class RecentsActivity extends BaseDraggingActivity { protected void onStart() { super.onStart(); UiFactory.onStart(this); mFallbackRecentsView.resetTaskVisuals(); } @Override Loading quickstep/src/com/android/quickstep/TaskUtils.java +167 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes quickstep/src/com/android/quickstep/util/MultiValueUpdateListener.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep.util; import android.animation.ValueAnimator; import android.view.animation.Interpolator; import java.util.ArrayList; /** * Utility class to update multiple values with different interpolators and durations during * the same animation. */ public abstract class MultiValueUpdateListener implements ValueAnimator.AnimatorUpdateListener { private final ArrayList<FloatProp> mAllProperties = new ArrayList<>(); @Override public final void onAnimationUpdate(ValueAnimator animator) { final float percent = animator.getAnimatedFraction(); final float currentPlayTime = percent * animator.getDuration(); for (int i = mAllProperties.size() - 1; i >= 0; i--) { FloatProp prop = mAllProperties.get(i); float time = Math.max(0, currentPlayTime - prop.mDelay); float newPercent = Math.min(1f, time / prop.mDuration); newPercent = prop.mInterpolator.getInterpolation(newPercent); prop.value = prop.mEnd * newPercent + prop.mStart * (1 - newPercent); } onUpdate(percent); } public abstract void onUpdate(float percent); public final class FloatProp { public float value; private final float mStart; private final float mEnd; private final float mDelay; private final float mDuration; private final Interpolator mInterpolator; public FloatProp(float start, float end, float delay, float duration, Interpolator i) { value = mStart = start; mEnd = end; mDelay = delay; mDuration = duration; mInterpolator = i; mAllProperties.add(this); } } } Loading
quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +36 −194 Original line number Diff line number Diff line Loading @@ -19,6 +19,13 @@ package com.android.launcher3; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT; import static com.android.launcher3.anim.Interpolators.APP_CLOSE_ALPHA; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.TaskUtils.findTaskViewToLaunch; import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber; import static com.android.systemui.shared.recents.utilities.Utilities.getSurface; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; Loading @@ -31,7 +38,6 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.ActivityOptions; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; Loading @@ -45,7 +51,6 @@ import android.util.Log; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.InsettableFrameLayout.LayoutParams; Loading @@ -55,12 +60,10 @@ import com.android.launcher3.anim.Interpolators; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.quickstep.RecentsAnimationInterpolator; import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; Loading @@ -79,7 +82,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag implements OnDeviceProfileChangeListener { private static final String TAG = "LauncherTransition"; private static final int STATUS_BAR_TRANSITION_DURATION = 120; public static final int STATUS_BAR_TRANSITION_DURATION = 120; private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION = "android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"; Loading @@ -87,7 +90,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag private static final int APP_LAUNCH_DURATION = 500; // Use a shorter duration for x or y translation to create a curve effect private static final int APP_LAUNCH_CURVED_DURATION = 233; private static final int RECENTS_LAUNCH_DURATION = 336; public static final int RECENTS_LAUNCH_DURATION = 336; private static final int LAUNCHER_RESUME_START_DELAY = 100; private static final int CLOSING_TRANSITION_DURATION_MS = 350; Loading Loading @@ -184,64 +187,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag mRemoteAnimationProvider = animationProvider; } /** * Try to find a TaskView that corresponds with the component of the launched view. * * If this method returns a non-null TaskView, it will be used in composeRecentsLaunchAnimation. * Otherwise, we will assume we are using a normal app transition, but it's possible that the * opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView. */ private TaskView findTaskViewToLaunch( BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) { if (v instanceof TaskView) { return (TaskView) v; } RecentsView recentsView = activity.getOverviewPanel(); // It's possible that the launched view can still be resolved to a visible task view, check // the task id of the opening task and see if we can find a match. if (v.getTag() instanceof ItemInfo) { ItemInfo itemInfo = (ItemInfo) v.getTag(); ComponentName componentName = itemInfo.getTargetComponent(); if (componentName != null) { for (int i = 0; i < recentsView.getChildCount(); i++) { TaskView taskView = (TaskView) recentsView.getPageAt(i); if (recentsView.isTaskViewVisible(taskView)) { Task task = taskView.getTask(); if (componentName.equals(task.key.getComponent())) { return taskView; } } } } } if (targets == null) { return null; } // Resolve the opening task id int openingTaskId = -1; for (RemoteAnimationTargetCompat target : targets) { if (target.mode == MODE_OPENING) { openingTaskId = target.taskId; break; } } // If there is no opening task id, fall back to the normal app icon launch animation if (openingTaskId == -1) { return null; } // If the opening task id is not currently visible in overview, then fall back to normal app // icon launch animation TaskView taskView = recentsView.getTaskView(openingTaskId); if (taskView == null || !recentsView.isTaskViewVisible(taskView)) { return null; } return taskView; } /** * Composes the animations for a launch from the recents list if possible. */ Loading Loading @@ -285,7 +230,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag }; } target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets)); target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets) .setDuration(RECENTS_LAUNCH_DURATION)); target.play(launcherAnim); // Set the current animation first, before adding windowAnimEndListener. Setting current Loading @@ -296,83 +242,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag return true; } /** * @return Animator that controls the window of the opening targets for the recents launch * animation. */ private ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipLauncherChanges, RemoteAnimationTargetCompat[] targets) { final RecentsAnimationInterpolator recentsInterpolator = v.getRecentsInterpolator(); 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.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { boolean isFirstFrame = true; @Override public void onAnimationUpdate(ValueAnimator animation) { final Surface surface = getSurface(v); final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1; if (frameNumber == -1) { // Booo, not cool! Our surface got destroyed, so no reason to animate anything. Log.w(TAG, "Failed to animate, surface got destroyed."); return; } 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, alphaDuration, alphaDuration, appAnimator.getDuration() * percent, Interpolators.LINEAR)); } matrix.setScale(tw.winScale, tw.winScale); matrix.postTranslate(tw.winX, tw.winY); crop.set(tw.winCrop); // Fade in the app window. float alpha = getValue(0f, 1f, 0, alphaDuration, appAnimator.getDuration() * percent, Interpolators.LINEAR); TransactionCompat t = new TransactionCompat(); for (RemoteAnimationTargetCompat target : targets) { if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) { t.setAlpha(target.leash, alpha); // TODO: This isn't correct at the beginning of the animation, but better // than nothing. matrix.postTranslate(target.position.x, target.position.y); t.setMatrix(target.leash, matrix); t.setWindowCrop(target.leash, crop); if (!skipLauncherChanges) { t.deferTransactionUntil(target.leash, surface, frameNumber); } } if (isFirstFrame) { t.show(target.leash); } } t.setEarlyWakeup(); t.apply(); matrix.reset(); isFirstFrame = false; } }); return appAnimator; } /** * Content is everything on screen except the background and the floating view (if any). * Loading @@ -399,9 +268,9 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas); alpha.setDuration(217); alpha.setInterpolator(Interpolators.LINEAR); alpha.setInterpolator(LINEAR); ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, trans); transY.setInterpolator(Interpolators.AGGRESSIVE_EASE); transY.setInterpolator(AGGRESSIVE_EASE); transY.setDuration(350); launcherAnimator.play(alpha); Loading @@ -420,10 +289,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, alphas); dragLayerAlpha.setDuration(217); dragLayerAlpha.setInterpolator(Interpolators.LINEAR); dragLayerAlpha.setInterpolator(LINEAR); ObjectAnimator dragLayerTransY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y, trans); dragLayerTransY.setInterpolator(Interpolators.AGGRESSIVE_EASE); dragLayerTransY.setInterpolator(AGGRESSIVE_EASE); dragLayerTransY.setDuration(350); launcherAnimator.play(dragLayerAlpha); Loading Loading @@ -515,8 +384,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag boolean isBelowCenterY = lp.topMargin < centerY; x.setDuration(isBelowCenterY ? APP_LAUNCH_DURATION : APP_LAUNCH_CURVED_DURATION); y.setDuration(isBelowCenterY ? APP_LAUNCH_CURVED_DURATION : APP_LAUNCH_DURATION); x.setInterpolator(Interpolators.AGGRESSIVE_EASE); y.setInterpolator(Interpolators.AGGRESSIVE_EASE); x.setInterpolator(AGGRESSIVE_EASE); y.setInterpolator(AGGRESSIVE_EASE); appIconAnimatorSet.play(x); appIconAnimatorSet.play(y); Loading @@ -534,7 +403,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator alpha = ObjectAnimator.ofFloat(mFloatingView, View.ALPHA, 1f, 0f); alpha.setStartDelay(32); alpha.setDuration(50); alpha.setInterpolator(Interpolators.LINEAR); alpha.setInterpolator(LINEAR); appIconAnimatorSet.play(alpha); appIconAnimatorSet.addListener(new AnimatorListenerAdapter() { Loading Loading @@ -569,11 +438,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setDuration(APP_LAUNCH_DURATION); appAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { appAnimator.addUpdateListener(new MultiValueUpdateListener() { // Fade alpha for the app window. FloatProp mAlpha = new FloatProp(0f, 1f, 0, 60, LINEAR); boolean isFirstFrame = true; @Override public void onAnimationUpdate(ValueAnimator animation) { public void onUpdate(float percent) { final Surface surface = getSurface(mFloatingView); final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1; if (frameNumber == -1) { Loading @@ -581,8 +453,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag Log.w(TAG, "Failed to animate, surface got destroyed."); return; } final float percent = animation.getAnimatedFraction(); final float easePercent = Interpolators.AGGRESSIVE_EASE.getInterpolation(percent); final float easePercent = AGGRESSIVE_EASE.getInterpolation(percent); // Calculate app icon size. float iconWidth = bounds.width() * mFloatingView.getScaleX(); Loading @@ -607,11 +478,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float transY0 = floatingViewBounds[1] - offsetY; matrix.postTranslate(transX0, transY0); // Fade in the app window. float alphaDuration = 60; float alpha = getValue(0f, 1f, 0, alphaDuration, appAnimator.getDuration() * percent, Interpolators.LINEAR); // Animate the window crop so that it starts off as a square, and then reveals // horizontally. float cropHeight = deviceHeight * easePercent + deviceWidth * (1 - easePercent); Loading @@ -624,7 +490,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag TransactionCompat t = new TransactionCompat(); for (RemoteAnimationTargetCompat target : targets) { if (target.mode == MODE_OPENING) { t.setAlpha(target.leash, alpha); t.setAlpha(target.leash, mAlpha.value); // TODO: This isn't correct at the beginning of the animation, but better // than nothing. Loading Loading @@ -670,13 +536,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) { int launcherTaskId = mLauncher.getTaskId(); for (RemoteAnimationTargetCompat target : targets) { if (target.mode == mode && target.taskId == launcherTaskId) { return true; } } return false; return taskIsATargetWithMode(targets, mLauncher.getTaskId(), mode); } /** Loading Loading @@ -730,30 +590,23 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1); closingAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS); closingAnimator.addUpdateListener(new MultiValueUpdateListener() { FloatProp mDx = new FloatProp(0, endX, 0, 350, AGGRESSIVE_EASE_IN_OUT); FloatProp mScale = new FloatProp(1f, 0.8f, 0, 267, AGGRESSIVE_EASE); FloatProp mAlpha = new FloatProp(1f, 0f, 0, 350, APP_CLOSE_ALPHA); closingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { boolean isFirstFrame = true; @Override public void onAnimationUpdate(ValueAnimator animation) { final float percent = animation.getAnimatedFraction(); float currentPlayTime = percent * closingAnimator.getDuration(); float scale = getValue(1f, 0.8f, 0, 267, currentPlayTime, Interpolators.AGGRESSIVE_EASE); float dX = getValue(0, endX, 0, 350, currentPlayTime, Interpolators.AGGRESSIVE_EASE_IN_OUT); public void onUpdate(float percent) { TransactionCompat t = new TransactionCompat(); for (RemoteAnimationTargetCompat app : targets) { if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) { t.setAlpha(app.leash, getValue(1f, 0f, 0, 350, currentPlayTime, Interpolators.APP_CLOSE_ALPHA)); matrix.setScale(scale, scale, t.setAlpha(app.leash, mAlpha.value); matrix.setScale(mScale.value, mScale.value, app.sourceContainerBounds.centerX(), app.sourceContainerBounds.centerY()); matrix.postTranslate(dX, 0); matrix.postTranslate(mDx.value, 0); matrix.postTranslate(app.position.x, app.position.y); t.setMatrix(app.leash, matrix); } Loading @@ -772,6 +625,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag isFirstFrame = false; } }); return closingAnimator; } Loading Loading @@ -832,16 +686,4 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION) == PackageManager.PERMISSION_GRANTED; } /** * Helper method that allows us to get interpolated values for embedded * animations with a delay and/or different duration. */ private static float getValue(float start, float end, float delay, float duration, float currentPlayTime, Interpolator i) { float time = Math.max(0, currentPlayTime - delay); float newPercent = Math.min(1f, time / duration); newPercent = i.getInterpolation(newPercent); return end * newPercent + start * (1 - newPercent); } }
quickstep/src/com/android/quickstep/RecentsActivity.java +63 −2 Original line number Diff line number Diff line Loading @@ -15,16 +15,29 @@ */ package com.android.quickstep; import static com.android.launcher3.LauncherAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.LauncherAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION; import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.app.ActivityOptions; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.View; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAnimationRunner; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.util.SystemUiController; Loading @@ -32,12 +45,18 @@ import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.fallback.RecentsRootView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; /** * A simple activity to show the recently launched tasks */ public class RecentsActivity extends BaseDraggingActivity { private Handler mUiHandler = new Handler(Looper.getMainLooper()); private RecentsRootView mRecentsRootView; private FallbackRecentsView mFallbackRecentsView; Loading Loading @@ -84,10 +103,51 @@ public class RecentsActivity extends BaseDraggingActivity { } @Override public ActivityOptions getActivityLaunchOptions(View v, boolean useDefaultLaunchOptions) { public ActivityOptions getActivityLaunchOptions(final View v, boolean useDefaultLaunchOptions) { if (useDefaultLaunchOptions || !(v instanceof TaskView)) { return null; } final TaskView taskView = (TaskView) v; RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler) { @Override public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) { return composeRecentsLaunchAnimator(taskView, targetCompats); } }; return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( runner, RECENTS_LAUNCH_DURATION, RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION)); } /** * Composes the animations for a launch from the recents list if possible. */ private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView, RemoteAnimationTargetCompat[] targets) { AnimatorSet target = new AnimatorSet(); boolean activityClosing = taskIsATargetWithMode(targets, getTaskId(), MODE_CLOSING); target.play(getRecentsWindowAnimator(taskView, !activityClosing, targets) .setDuration(RECENTS_LAUNCH_DURATION)); // Found a visible recents task that matches the opening app, lets launch the app from there if (activityClosing) { Animator adjacentAnimation = mFallbackRecentsView .createAdjacentPageAnimForTaskLaunch(taskView); adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION); adjacentAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mFallbackRecentsView.resetTaskVisuals(); } }); target.play(adjacentAnimation); } return target; } @Override public void invalidateParent(ItemInfo info) { } Loading @@ -95,6 +155,7 @@ public class RecentsActivity extends BaseDraggingActivity { protected void onStart() { super.onStart(); UiFactory.onStart(this); mFallbackRecentsView.resetTaskVisuals(); } @Override Loading
quickstep/src/com/android/quickstep/TaskUtils.java +167 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes
quickstep/src/com/android/quickstep/util/MultiValueUpdateListener.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep.util; import android.animation.ValueAnimator; import android.view.animation.Interpolator; import java.util.ArrayList; /** * Utility class to update multiple values with different interpolators and durations during * the same animation. */ public abstract class MultiValueUpdateListener implements ValueAnimator.AnimatorUpdateListener { private final ArrayList<FloatProp> mAllProperties = new ArrayList<>(); @Override public final void onAnimationUpdate(ValueAnimator animator) { final float percent = animator.getAnimatedFraction(); final float currentPlayTime = percent * animator.getDuration(); for (int i = mAllProperties.size() - 1; i >= 0; i--) { FloatProp prop = mAllProperties.get(i); float time = Math.max(0, currentPlayTime - prop.mDelay); float newPercent = Math.min(1f, time / prop.mDuration); newPercent = prop.mInterpolator.getInterpolation(newPercent); prop.value = prop.mEnd * newPercent + prop.mStart * (1 - newPercent); } onUpdate(percent); } public abstract void onUpdate(float percent); public final class FloatProp { public float value; private final float mStart; private final float mEnd; private final float mDelay; private final float mDuration; private final Interpolator mInterpolator; public FloatProp(float start, float end, float delay, float duration, Interpolator i) { value = mStart = start; mEnd = end; mDelay = delay; mDuration = duration; mInterpolator = i; mAllProperties.add(this); } } }