Loading quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +119 −0 Original line number Diff line number Diff line Loading @@ -19,12 +19,15 @@ import static android.os.VibrationEffect.EFFECT_CLICK; import static android.os.VibrationEffect.createPredefined; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR; import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR; import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import android.animation.Animator; import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; Loading @@ -32,6 +35,7 @@ import android.content.Intent; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; import android.os.Handler; import android.os.Looper; Loading @@ -48,12 +52,19 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.ActivityControlHelper.ActivityInitListener; import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.inputconsumers.InputConsumer; import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper.TransformParams; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.SwipeAnimationTargetSet; import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener; import com.android.quickstep.views.RecentsView; Loading Loading @@ -369,9 +380,117 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten return TaskView.getCurveScaleForInterpolation(interpolation); } /** * Creates an animation that transforms the current app window into the home app. * @param startProgress The progress of {@link #mCurrentShift} to start the window from. * @param homeAnimationFactory The home animation factory. */ protected RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet; final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet, mTransformParams.setProgress(startProgress), false /* launcherOnTop */)); final RectF targetRect = homeAnimationFactory.getWindowTargetRect(); final View floatingView = homeAnimationFactory.getFloatingView(); final boolean isFloatingIconView = floatingView instanceof FloatingIconView; RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext.getResources()); if (isFloatingIconView) { FloatingIconView fiv = (FloatingIconView) floatingView; anim.addAnimatorListener(fiv); fiv.setOnTargetChangeListener(anim::onTargetPositionChanged); } AnimatorPlaybackController homeAnim = homeAnimationFactory.createActivityAnimationToHome(); // End on a "round-enough" radius so that the shape reveal doesn't have to do too much // rounding at the end of the animation. float startRadius = mClipAnimationHelper.getCurrentCornerRadius(); float endRadius = startRect.width() / 6f; // We want the window alpha to be 0 once this threshold is met, so that the // FolderIconView can be seen morphing into the icon shape. final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f; anim.addOnUpdateListener(new RectFSpringAnim.OnUpdateListener() { @Override public void onUpdate(RectF currentRect, float progress) { homeAnim.setPlayFraction(progress); float alphaProgress = ACCEL_1_5.getInterpolation(progress); float windowAlpha = Utilities.boundToRange(Utilities.mapToRange(alphaProgress, 0, windowAlphaThreshold, 1.5f, 0f, Interpolators.LINEAR), 0, 1); mTransformParams.setProgress(progress) .setCurrentRectAndTargetAlpha(currentRect, windowAlpha); if (isFloatingIconView) { mTransformParams.setCornerRadius(endRadius * progress + startRadius * (1f - progress)); } mClipAnimationHelper.applyTransform(targetSet, mTransformParams, false /* launcherOnTop */); if (isFloatingIconView) { ((FloatingIconView) floatingView).update(currentRect, 1f, progress, windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false); } } @Override public void onCancel() { if (isFloatingIconView) { ((FloatingIconView) floatingView).fastFinish(); } } }); anim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { homeAnim.dispatchOnStart(); } @Override public void onAnimationSuccess(Animator animator) { homeAnim.getAnimationPlayer().end(); } }); return anim; } public interface Factory { BaseSwipeUpHandler newHandler(RunningTaskInfo runningTask, long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask); } protected interface RunningWindowAnim { void end(); void cancel(); static RunningWindowAnim wrap(Animator animator) { return new RunningWindowAnim() { @Override public void end() { animator.end(); } @Override public void cancel() { animator.cancel(); } }; } static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) { return new RunningWindowAnim() { @Override public void end() { rectFSpringAnim.end(); } @Override public void cancel() { rectFSpringAnim.cancel(); } }; } } } quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +1 −7 Original line number Diff line number Diff line Loading @@ -151,16 +151,10 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe @NonNull @Override public RectF getWindowTargetRect() { final int halfIconSize = dp.iconSizePx / 2; final float targetCenterX = dp.availableWidthPx / 2f; final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx; if (canUseWorkspaceView) { return iconLocation; } else { // Fallback to animate to center of screen. return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize, targetCenterX + halfIconSize, targetCenterY + halfIconSize); return HomeAnimationFactory.getDefaultWindowTargetRect(dp); } } Loading quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +5 −98 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.quickstep; import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; Loading @@ -27,7 +26,6 @@ import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS; import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW; import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE; import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK; import static com.android.quickstep.MultiStateCallback.DEBUG_STATES; Loading @@ -52,7 +50,6 @@ import android.graphics.PointF; import android.graphics.RectF; import android.os.Build; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.view.View.OnApplyWindowInsetsListener; import android.view.ViewTreeObserver.OnDrawListener; Loading @@ -68,13 +65,11 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.ActivityControlHelper.AnimationFactory; import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState; import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory; Loading @@ -83,7 +78,6 @@ import com.android.quickstep.inputconsumers.InputConsumer; import com.android.quickstep.inputconsumers.OverviewInputConsumer; import com.android.quickstep.util.ClipAnimationHelper.TargetAlphaProvider; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.SwipeAnimationTargetSet; import com.android.quickstep.views.LiveTileOverlay; import com.android.quickstep.views.RecentsView; Loading Loading @@ -968,67 +962,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> * @param startProgress The progress of {@link #mCurrentShift} to start the window from. * @param homeAnimationFactory The home animation factory. */ private RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet; final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet, mTransformParams.setProgress(startProgress), false /* launcherOnTop */)); final RectF targetRect = homeAnimationFactory.getWindowTargetRect(); final View floatingView = homeAnimationFactory.getFloatingView(); final boolean isFloatingIconView = floatingView instanceof FloatingIconView; RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mActivity.getResources()); if (isFloatingIconView) { FloatingIconView fiv = (FloatingIconView) floatingView; anim.addAnimatorListener(fiv); fiv.setOnTargetChangeListener(anim::onTargetPositionChanged); } AnimatorPlaybackController homeAnim = homeAnimationFactory.createActivityAnimationToHome(); // End on a "round-enough" radius so that the shape reveal doesn't have to do too much // rounding at the end of the animation. float startRadius = mClipAnimationHelper.getCurrentCornerRadius(); float endRadius = startRect.width() / 6f; // We want the window alpha to be 0 once this threshold is met, so that the // FolderIconView can be seen morphing into the icon shape. final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f; anim.addOnUpdateListener(new RectFSpringAnim.OnUpdateListener() { @Override public void onUpdate(RectF currentRect, float progress) { homeAnim.setPlayFraction(progress); float alphaProgress = ACCEL_1_5.getInterpolation(progress); float windowAlpha = Utilities.boundToRange(Utilities.mapToRange(alphaProgress, 0, windowAlphaThreshold, 1.5f, 0f, Interpolators.LINEAR), 0, 1); mTransformParams.setProgress(progress) .setCurrentRectAndTargetAlpha(currentRect, windowAlpha); if (isFloatingIconView) { mTransformParams.setCornerRadius(endRadius * progress + startRadius * (1f - progress)); } mClipAnimationHelper.applyTransform(targetSet, mTransformParams, false /* launcherOnTop */); if (isFloatingIconView) { ((FloatingIconView) floatingView).update(currentRect, 1f, progress, windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false); } updateSysUiFlags(Math.max(progress, mCurrentShift.value)); } @Override public void onCancel() { if (isFloatingIconView) { ((FloatingIconView) floatingView).fastFinish(); } } }); protected RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { RectFSpringAnim anim = super.createWindowAnimationToHome(startProgress, homeAnimationFactory); anim.addOnUpdateListener((r, p) -> updateSysUiFlags(Math.max(p, mCurrentShift.value))); anim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { homeAnim.dispatchOnStart(); if (mActivity != null) { mActivity.getRootView().getOverlay().remove(mLiveTileOverlay); } Loading @@ -1036,7 +978,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> @Override public void onAnimationSuccess(Animator animator) { homeAnim.getAnimationPlayer().end(); if (mRecentsView != null) { mRecentsView.post(mRecentsView::resetTaskVisuals); } Loading Loading @@ -1270,38 +1211,4 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> return app.isNotInRecents || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; } private interface RunningWindowAnim { void end(); void cancel(); static RunningWindowAnim wrap(Animator animator) { return new RunningWindowAnim() { @Override public void end() { animator.end(); } @Override public void cancel() { animator.cancel(); } }; } static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) { return new RunningWindowAnim() { @Override public void end() { rectFSpringAnim.end(); } @Override public void cancel() { rectFSpringAnim.cancel(); } }; } } } quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java +62 −22 Original line number Diff line number Diff line Loading @@ -18,11 +18,12 @@ package com.android.quickstep.inputconsumers; import static com.android.quickstep.MultiStateCallback.DEBUG_STATES; import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID; import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK; import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.HOME; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.LAST_TASK; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS; import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD; import android.animation.Animator; import android.animation.AnimatorSet; Loading @@ -31,10 +32,13 @@ import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.graphics.PointF; import android.graphics.RectF; import android.os.Bundle; import com.android.launcher3.R; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.BaseSwipeUpHandler; import com.android.quickstep.MultiStateCallback; Loading @@ -44,6 +48,7 @@ import com.android.quickstep.RecentsModel; import com.android.quickstep.SwipeSharedState; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.util.ObjectWrapper; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.SwipeAnimationTargetSet; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; Loading Loading @@ -102,10 +107,10 @@ public class FallbackNoButtonInputConsumer extends private final boolean mRunningOverHome; private final boolean mSwipeUpOverHome; private final RunningTaskInfo mRunningTaskInfo; private Animator mFinishAnimation; private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f); private RunningWindowAnim mFinishAnimation; public FallbackNoButtonInputConsumer(Context context, OverviewComponentObserver overviewComponentObserver, Loading Loading @@ -226,6 +231,8 @@ public class FallbackNoButtonInputConsumer extends @Override public void updateFinalShift() { mTransformParams.setProgress(mCurrentShift.value); mRecentsAnimationWrapper.setWindowThresholdCrossed(!mInQuickSwitchMode && (mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD)); if (mRecentsAnimationWrapper.targetSet != null) { applyTransformUnchecked(); } Loading @@ -240,6 +247,7 @@ public class FallbackNoButtonInputConsumer extends @Override public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) { mEndVelocityPxPerMs.set(0, velocity.y / 1000); if (mInQuickSwitchMode) { // For now set it to non-null, it will be reset before starting the animation mEndTarget = LAST_TASK; Loading Loading @@ -288,12 +296,14 @@ public class FallbackNoButtonInputConsumer extends } } private void onHandlerInvalidated() { mActivityInitListener.unregister(); if (mGestureEndCallback != null) { mGestureEndCallback.run(); } if (mFinishAnimation != null) { mFinishAnimation.end(); } } private void onHandlerInvalidatedWithRecents() { Loading Loading @@ -364,31 +374,39 @@ public class FallbackNoButtonInputConsumer extends } float endProgress = mEndTarget.mEndProgress; if (mCurrentShift.value != endProgress || mInQuickSwitchMode) { AnimatorSet anim = new AnimatorSet(); anim.play(mLauncherAlpha.animateToValue( mLauncherAlpha.value, mEndTarget.mLauncherAlpha)); anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress)); long duration = (long) (mEndTarget.mDurationMultiplier * Math.abs(endProgress - mCurrentShift.value)); if (mRecentsView != null) { duration = Math.max(duration, mRecentsView.getScroller().getDuration()); } anim.setDuration(duration); anim.addListener(new AnimationSuccessListener() { if (mCurrentShift.value != endProgress || mInQuickSwitchMode) { AnimationSuccessListener endListener = new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { finishAnimationTargetSetAnimationComplete(); mFinishAnimation = null; } }); }; if (mEndTarget == HOME && !mRunningOverHome) { RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration); anim.addAnimatorListener(endListener); anim.start(mEndVelocityPxPerMs); mFinishAnimation = RunningWindowAnim.wrap(anim); } else { AnimatorSet anim = new AnimatorSet(); anim.play(mLauncherAlpha.animateToValue( mLauncherAlpha.value, mEndTarget.mLauncherAlpha)); anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress)); anim.setDuration(duration); anim.addListener(endListener); anim.start(); mFinishAnimation = anim; mFinishAnimation = RunningWindowAnim.wrap(anim); } } else { finishAnimationTargetSetAnimationComplete(); } Loading @@ -412,4 +430,26 @@ public class FallbackNoButtonInputConsumer extends mRecentsAnimationWrapper.setController(null); setStateOnUiThread(STATE_HANDLER_INVALIDATED); } /** * Creates an animation that transforms the current app window into the home app. * @param startProgress The progress of {@link #mCurrentShift} to start the window from. */ private RectFSpringAnim createWindowAnimationToHome(float startProgress, long duration) { HomeAnimationFactory factory = new HomeAnimationFactory() { @Override public RectF getWindowTargetRect() { return HomeAnimationFactory.getDefaultWindowTargetRect(mDp); } @Override public AnimatorPlaybackController createActivityAnimationToHome() { AnimatorSet anim = new AnimatorSet(); anim.play(mLauncherAlpha.animateToValue(mLauncherAlpha.value, 1)); anim.setDuration(duration); return AnimatorPlaybackController.wrap(anim, duration); } }; return createWindowAnimationToHome(startProgress, factory); } } quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java +1 −1 Original line number Diff line number Diff line Loading @@ -237,6 +237,6 @@ public class RectFSpringAnim { public interface OnUpdateListener { void onUpdate(RectF currentRect, float progress); void onCancel(); default void onCancel() { } } } Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +119 −0 Original line number Diff line number Diff line Loading @@ -19,12 +19,15 @@ import static android.os.VibrationEffect.EFFECT_CLICK; import static android.os.VibrationEffect.createPredefined; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR; import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR; import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import android.animation.Animator; import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; Loading @@ -32,6 +35,7 @@ import android.content.Intent; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; import android.os.Handler; import android.os.Looper; Loading @@ -48,12 +52,19 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.ActivityControlHelper.ActivityInitListener; import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.inputconsumers.InputConsumer; import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper.TransformParams; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.SwipeAnimationTargetSet; import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener; import com.android.quickstep.views.RecentsView; Loading Loading @@ -369,9 +380,117 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten return TaskView.getCurveScaleForInterpolation(interpolation); } /** * Creates an animation that transforms the current app window into the home app. * @param startProgress The progress of {@link #mCurrentShift} to start the window from. * @param homeAnimationFactory The home animation factory. */ protected RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet; final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet, mTransformParams.setProgress(startProgress), false /* launcherOnTop */)); final RectF targetRect = homeAnimationFactory.getWindowTargetRect(); final View floatingView = homeAnimationFactory.getFloatingView(); final boolean isFloatingIconView = floatingView instanceof FloatingIconView; RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext.getResources()); if (isFloatingIconView) { FloatingIconView fiv = (FloatingIconView) floatingView; anim.addAnimatorListener(fiv); fiv.setOnTargetChangeListener(anim::onTargetPositionChanged); } AnimatorPlaybackController homeAnim = homeAnimationFactory.createActivityAnimationToHome(); // End on a "round-enough" radius so that the shape reveal doesn't have to do too much // rounding at the end of the animation. float startRadius = mClipAnimationHelper.getCurrentCornerRadius(); float endRadius = startRect.width() / 6f; // We want the window alpha to be 0 once this threshold is met, so that the // FolderIconView can be seen morphing into the icon shape. final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f; anim.addOnUpdateListener(new RectFSpringAnim.OnUpdateListener() { @Override public void onUpdate(RectF currentRect, float progress) { homeAnim.setPlayFraction(progress); float alphaProgress = ACCEL_1_5.getInterpolation(progress); float windowAlpha = Utilities.boundToRange(Utilities.mapToRange(alphaProgress, 0, windowAlphaThreshold, 1.5f, 0f, Interpolators.LINEAR), 0, 1); mTransformParams.setProgress(progress) .setCurrentRectAndTargetAlpha(currentRect, windowAlpha); if (isFloatingIconView) { mTransformParams.setCornerRadius(endRadius * progress + startRadius * (1f - progress)); } mClipAnimationHelper.applyTransform(targetSet, mTransformParams, false /* launcherOnTop */); if (isFloatingIconView) { ((FloatingIconView) floatingView).update(currentRect, 1f, progress, windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false); } } @Override public void onCancel() { if (isFloatingIconView) { ((FloatingIconView) floatingView).fastFinish(); } } }); anim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { homeAnim.dispatchOnStart(); } @Override public void onAnimationSuccess(Animator animator) { homeAnim.getAnimationPlayer().end(); } }); return anim; } public interface Factory { BaseSwipeUpHandler newHandler(RunningTaskInfo runningTask, long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask); } protected interface RunningWindowAnim { void end(); void cancel(); static RunningWindowAnim wrap(Animator animator) { return new RunningWindowAnim() { @Override public void end() { animator.end(); } @Override public void cancel() { animator.cancel(); } }; } static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) { return new RunningWindowAnim() { @Override public void end() { rectFSpringAnim.end(); } @Override public void cancel() { rectFSpringAnim.cancel(); } }; } } }
quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +1 −7 Original line number Diff line number Diff line Loading @@ -151,16 +151,10 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe @NonNull @Override public RectF getWindowTargetRect() { final int halfIconSize = dp.iconSizePx / 2; final float targetCenterX = dp.availableWidthPx / 2f; final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx; if (canUseWorkspaceView) { return iconLocation; } else { // Fallback to animate to center of screen. return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize, targetCenterX + halfIconSize, targetCenterY + halfIconSize); return HomeAnimationFactory.getDefaultWindowTargetRect(dp); } } Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +5 −98 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.quickstep; import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; Loading @@ -27,7 +26,6 @@ import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS; import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW; import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE; import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK; import static com.android.quickstep.MultiStateCallback.DEBUG_STATES; Loading @@ -52,7 +50,6 @@ import android.graphics.PointF; import android.graphics.RectF; import android.os.Build; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.view.View.OnApplyWindowInsetsListener; import android.view.ViewTreeObserver.OnDrawListener; Loading @@ -68,13 +65,11 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.ActivityControlHelper.AnimationFactory; import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState; import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory; Loading @@ -83,7 +78,6 @@ import com.android.quickstep.inputconsumers.InputConsumer; import com.android.quickstep.inputconsumers.OverviewInputConsumer; import com.android.quickstep.util.ClipAnimationHelper.TargetAlphaProvider; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.SwipeAnimationTargetSet; import com.android.quickstep.views.LiveTileOverlay; import com.android.quickstep.views.RecentsView; Loading Loading @@ -968,67 +962,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> * @param startProgress The progress of {@link #mCurrentShift} to start the window from. * @param homeAnimationFactory The home animation factory. */ private RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet; final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet, mTransformParams.setProgress(startProgress), false /* launcherOnTop */)); final RectF targetRect = homeAnimationFactory.getWindowTargetRect(); final View floatingView = homeAnimationFactory.getFloatingView(); final boolean isFloatingIconView = floatingView instanceof FloatingIconView; RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mActivity.getResources()); if (isFloatingIconView) { FloatingIconView fiv = (FloatingIconView) floatingView; anim.addAnimatorListener(fiv); fiv.setOnTargetChangeListener(anim::onTargetPositionChanged); } AnimatorPlaybackController homeAnim = homeAnimationFactory.createActivityAnimationToHome(); // End on a "round-enough" radius so that the shape reveal doesn't have to do too much // rounding at the end of the animation. float startRadius = mClipAnimationHelper.getCurrentCornerRadius(); float endRadius = startRect.width() / 6f; // We want the window alpha to be 0 once this threshold is met, so that the // FolderIconView can be seen morphing into the icon shape. final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f; anim.addOnUpdateListener(new RectFSpringAnim.OnUpdateListener() { @Override public void onUpdate(RectF currentRect, float progress) { homeAnim.setPlayFraction(progress); float alphaProgress = ACCEL_1_5.getInterpolation(progress); float windowAlpha = Utilities.boundToRange(Utilities.mapToRange(alphaProgress, 0, windowAlphaThreshold, 1.5f, 0f, Interpolators.LINEAR), 0, 1); mTransformParams.setProgress(progress) .setCurrentRectAndTargetAlpha(currentRect, windowAlpha); if (isFloatingIconView) { mTransformParams.setCornerRadius(endRadius * progress + startRadius * (1f - progress)); } mClipAnimationHelper.applyTransform(targetSet, mTransformParams, false /* launcherOnTop */); if (isFloatingIconView) { ((FloatingIconView) floatingView).update(currentRect, 1f, progress, windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false); } updateSysUiFlags(Math.max(progress, mCurrentShift.value)); } @Override public void onCancel() { if (isFloatingIconView) { ((FloatingIconView) floatingView).fastFinish(); } } }); protected RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { RectFSpringAnim anim = super.createWindowAnimationToHome(startProgress, homeAnimationFactory); anim.addOnUpdateListener((r, p) -> updateSysUiFlags(Math.max(p, mCurrentShift.value))); anim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { homeAnim.dispatchOnStart(); if (mActivity != null) { mActivity.getRootView().getOverlay().remove(mLiveTileOverlay); } Loading @@ -1036,7 +978,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> @Override public void onAnimationSuccess(Animator animator) { homeAnim.getAnimationPlayer().end(); if (mRecentsView != null) { mRecentsView.post(mRecentsView::resetTaskVisuals); } Loading Loading @@ -1270,38 +1211,4 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> return app.isNotInRecents || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; } private interface RunningWindowAnim { void end(); void cancel(); static RunningWindowAnim wrap(Animator animator) { return new RunningWindowAnim() { @Override public void end() { animator.end(); } @Override public void cancel() { animator.cancel(); } }; } static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) { return new RunningWindowAnim() { @Override public void end() { rectFSpringAnim.end(); } @Override public void cancel() { rectFSpringAnim.cancel(); } }; } } }
quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java +62 −22 Original line number Diff line number Diff line Loading @@ -18,11 +18,12 @@ package com.android.quickstep.inputconsumers; import static com.android.quickstep.MultiStateCallback.DEBUG_STATES; import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID; import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK; import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.HOME; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.LAST_TASK; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK; import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS; import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD; import android.animation.Animator; import android.animation.AnimatorSet; Loading @@ -31,10 +32,13 @@ import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.graphics.PointF; import android.graphics.RectF; import android.os.Bundle; import com.android.launcher3.R; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.BaseSwipeUpHandler; import com.android.quickstep.MultiStateCallback; Loading @@ -44,6 +48,7 @@ import com.android.quickstep.RecentsModel; import com.android.quickstep.SwipeSharedState; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.util.ObjectWrapper; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.SwipeAnimationTargetSet; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; Loading Loading @@ -102,10 +107,10 @@ public class FallbackNoButtonInputConsumer extends private final boolean mRunningOverHome; private final boolean mSwipeUpOverHome; private final RunningTaskInfo mRunningTaskInfo; private Animator mFinishAnimation; private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f); private RunningWindowAnim mFinishAnimation; public FallbackNoButtonInputConsumer(Context context, OverviewComponentObserver overviewComponentObserver, Loading Loading @@ -226,6 +231,8 @@ public class FallbackNoButtonInputConsumer extends @Override public void updateFinalShift() { mTransformParams.setProgress(mCurrentShift.value); mRecentsAnimationWrapper.setWindowThresholdCrossed(!mInQuickSwitchMode && (mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD)); if (mRecentsAnimationWrapper.targetSet != null) { applyTransformUnchecked(); } Loading @@ -240,6 +247,7 @@ public class FallbackNoButtonInputConsumer extends @Override public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) { mEndVelocityPxPerMs.set(0, velocity.y / 1000); if (mInQuickSwitchMode) { // For now set it to non-null, it will be reset before starting the animation mEndTarget = LAST_TASK; Loading Loading @@ -288,12 +296,14 @@ public class FallbackNoButtonInputConsumer extends } } private void onHandlerInvalidated() { mActivityInitListener.unregister(); if (mGestureEndCallback != null) { mGestureEndCallback.run(); } if (mFinishAnimation != null) { mFinishAnimation.end(); } } private void onHandlerInvalidatedWithRecents() { Loading Loading @@ -364,31 +374,39 @@ public class FallbackNoButtonInputConsumer extends } float endProgress = mEndTarget.mEndProgress; if (mCurrentShift.value != endProgress || mInQuickSwitchMode) { AnimatorSet anim = new AnimatorSet(); anim.play(mLauncherAlpha.animateToValue( mLauncherAlpha.value, mEndTarget.mLauncherAlpha)); anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress)); long duration = (long) (mEndTarget.mDurationMultiplier * Math.abs(endProgress - mCurrentShift.value)); if (mRecentsView != null) { duration = Math.max(duration, mRecentsView.getScroller().getDuration()); } anim.setDuration(duration); anim.addListener(new AnimationSuccessListener() { if (mCurrentShift.value != endProgress || mInQuickSwitchMode) { AnimationSuccessListener endListener = new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { finishAnimationTargetSetAnimationComplete(); mFinishAnimation = null; } }); }; if (mEndTarget == HOME && !mRunningOverHome) { RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration); anim.addAnimatorListener(endListener); anim.start(mEndVelocityPxPerMs); mFinishAnimation = RunningWindowAnim.wrap(anim); } else { AnimatorSet anim = new AnimatorSet(); anim.play(mLauncherAlpha.animateToValue( mLauncherAlpha.value, mEndTarget.mLauncherAlpha)); anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress)); anim.setDuration(duration); anim.addListener(endListener); anim.start(); mFinishAnimation = anim; mFinishAnimation = RunningWindowAnim.wrap(anim); } } else { finishAnimationTargetSetAnimationComplete(); } Loading @@ -412,4 +430,26 @@ public class FallbackNoButtonInputConsumer extends mRecentsAnimationWrapper.setController(null); setStateOnUiThread(STATE_HANDLER_INVALIDATED); } /** * Creates an animation that transforms the current app window into the home app. * @param startProgress The progress of {@link #mCurrentShift} to start the window from. */ private RectFSpringAnim createWindowAnimationToHome(float startProgress, long duration) { HomeAnimationFactory factory = new HomeAnimationFactory() { @Override public RectF getWindowTargetRect() { return HomeAnimationFactory.getDefaultWindowTargetRect(mDp); } @Override public AnimatorPlaybackController createActivityAnimationToHome() { AnimatorSet anim = new AnimatorSet(); anim.play(mLauncherAlpha.animateToValue(mLauncherAlpha.value, 1)); anim.setDuration(duration); return AnimatorPlaybackController.wrap(anim, duration); } }; return createWindowAnimationToHome(startProgress, factory); } }
quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java +1 −1 Original line number Diff line number Diff line Loading @@ -237,6 +237,6 @@ public class RectFSpringAnim { public interface OnUpdateListener { void onUpdate(RectF currentRect, float progress); void onCancel(); default void onCancel() { } } }