diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 18337d3991..2c726ffb77 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -214,6 +214,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener public static final int CONTENT_ALPHA_DURATION = 217; public static final int TRANSIENT_TASKBAR_TRANSITION_DURATION = 417; + public static final int PINNED_TASKBAR_TRANSITION_DURATION = 600; public static final int TASKBAR_TO_APP_DURATION = 600; // TODO(b/236145847): Tune TASKBAR_TO_HOME_DURATION to 383 after conflict with unlock animation // is solved. @@ -1726,8 +1727,21 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener return new AnimatorBackState(rectFSpringAnim, anim); } - public static int getTaskbarToHomeDuration() { - if (enableScalingRevealHomeAnimation()) { + /** Get animation duration for taskbar for going to home. */ + public static int getTaskbarToHomeDuration(boolean isPinnedTaskbar) { + return getTaskbarToHomeDuration(false, isPinnedTaskbar); + } + + /** + * Get animation duration for taskbar for going to home. + * + * @param shouldOverrideToFastAnimation should overwrite scaling reveal home animation duration + */ + public static int getTaskbarToHomeDuration(boolean shouldOverrideToFastAnimation, + boolean isPinnedTaskbar) { + if (isPinnedTaskbar) { + return PINNED_TASKBAR_TRANSITION_DURATION; + } else if (enableScalingRevealHomeAnimation() && !shouldOverrideToFastAnimation) { return TASKBAR_TO_HOME_DURATION_SLOW; } else { return TASKBAR_TO_HOME_DURATION_FAST; diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 4a94be71bb..53b8f61d26 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -210,8 +210,12 @@ public class LauncherTaskbarUIController extends TaskbarUIController { } private int getTaskbarAnimationDuration(boolean isVisible) { - if (isVisible && !mLauncher.getPredictiveBackToHomeInProgress()) { - return getTaskbarToHomeDuration(); + // fast animation duration since we will not be playing workspace reveal animation. + boolean shouldOverrideToFastAnimation = + !isHotseatIconOnTopWhenAligned() || mLauncher.getPredictiveBackToHomeInProgress(); + boolean isPinnedTaskbar = DisplayController.isPinnedTaskbar(mLauncher); + if (isVisible || isPinnedTaskbar) { + return getTaskbarToHomeDuration(shouldOverrideToFastAnimation, isPinnedTaskbar); } else { return DisplayController.isTransientTaskbar(mLauncher) ? TRANSIENT_TASKBAR_TRANSITION_DURATION diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index fa0473910b..29988927bb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -17,6 +17,7 @@ package com.android.launcher3.taskbar; import static com.android.app.animation.Interpolators.EMPHASIZED; import static com.android.app.animation.Interpolators.FINAL_FRAME; +import static com.android.app.animation.Interpolators.INSTANT; import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation; import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_ALIGNMENT; import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_STASH; @@ -222,7 +223,9 @@ public class TaskbarLauncherStateController { updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, true); if (!mShouldDelayLauncherStateAnim) { if (toState == LauncherState.NORMAL) { - applyState(QuickstepTransitionManager.getTaskbarToHomeDuration()); + applyState(QuickstepTransitionManager.getTaskbarToHomeDuration( + DisplayController.isPinnedTaskbar( + mControllers.taskbarActivityContext))); } else { applyState(); } @@ -459,9 +462,12 @@ public class TaskbarLauncherStateController { private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) { final boolean isInLauncher = isInLauncher(); + final boolean isInOverview = mControllers.uiController.isInOverviewUi(); final boolean isIconAlignedWithHotseat = isIconAlignedWithHotseat(); final float toAlignment = isIconAlignedWithHotseat ? 1 : 0; boolean handleOpenFloatingViews = false; + boolean isPinnedTaskbar = DisplayController.isPinnedTaskbar( + mControllers.taskbarActivityContext); if (DEBUG) { Log.d(TAG, "onStateChangeApplied - isInLauncher: " + isInLauncher + ", mLauncherState: " + mLauncherState @@ -573,10 +579,17 @@ public class TaskbarLauncherStateController { } float backgroundAlpha = isInLauncher && isTaskbarAlignedWithHotseat() ? 0 : 1; + AnimatedFloat taskbarBgOffset = + mControllers.taskbarDragLayerController.getTaskbarBackgroundOffset(); + boolean showTaskbar = !isInLauncher || isInOverview; + float taskbarBgOffsetEnd = showTaskbar ? 0f : 1f; + float taskbarBgOffsetStart = showTaskbar ? 1f : 0f; // Don't animate if background has reached desired value. if (mTaskbarBackgroundAlpha.isAnimating() - || mTaskbarBackgroundAlpha.value != backgroundAlpha) { + || mTaskbarBackgroundAlpha.value != backgroundAlpha + || taskbarBgOffset.isAnimatingToValue(taskbarBgOffsetStart) + || taskbarBgOffset.value != taskbarBgOffsetEnd) { mTaskbarBackgroundAlpha.cancelAnimation(); if (DEBUG) { Log.d(TAG, "onStateChangeApplied - taskbarBackgroundAlpha - " @@ -587,25 +600,35 @@ public class TaskbarLauncherStateController { boolean isInLauncherIconNotAligned = isInLauncher && !isIconAlignedWithHotseat; boolean notInLauncherIconNotAligned = !isInLauncher && !isIconAlignedWithHotseat; boolean isInLauncherIconIsAligned = isInLauncher && isIconAlignedWithHotseat; + // When Hotseat icons are not on top don't change duration or add start delay. + // This will keep the duration in sync for icon alignment and background fade in/out. + // For example, launching app from launcher all apps. + boolean isHotseatIconOnTopWhenAligned = + mControllers.uiController.isHotseatIconOnTopWhenAligned(); float startDelay = 0; // We want to delay the background from fading in so that the icons have time to move // into the bounds of the background before it appears. if (isInLauncherIconNotAligned) { startDelay = duration * TASKBAR_BG_ALPHA_LAUNCHER_NOT_ALIGNED_DELAY_MULT; - } else if (notInLauncherIconNotAligned) { + } else if (notInLauncherIconNotAligned && isHotseatIconOnTopWhenAligned) { startDelay = duration * TASKBAR_BG_ALPHA_NOT_LAUNCHER_NOT_ALIGNED_DELAY_MULT; } float newDuration = duration - startDelay; - if (isInLauncherIconIsAligned) { + if (isInLauncherIconIsAligned && isHotseatIconOnTopWhenAligned) { // Make the background fade out faster so that it is gone by the time the // icons move outside of the bounds of the background. newDuration = duration * TASKBAR_BG_ALPHA_LAUNCHER_IS_ALIGNED_DURATION_MULT; } - Animator taskbarBackgroundAlpha = mTaskbarBackgroundAlpha - .animateToValue(backgroundAlpha) - .setDuration((long) newDuration); - taskbarBackgroundAlpha.setStartDelay((long) startDelay); + Animator taskbarBackgroundAlpha = mTaskbarBackgroundAlpha.animateToValue( + backgroundAlpha); + if (isPinnedTaskbar) { + setupPinnedTaskbarAnimation(animatorSet, showTaskbar, taskbarBgOffset, + taskbarBgOffsetStart, taskbarBgOffsetEnd, duration, taskbarBackgroundAlpha); + } else { + taskbarBackgroundAlpha.setDuration((long) newDuration); + taskbarBackgroundAlpha.setStartDelay((long) startDelay); + } animatorSet.play(taskbarBackgroundAlpha); } @@ -671,15 +694,18 @@ public class TaskbarLauncherStateController { + mIconAlignment.value + " -> " + toAlignment + ": " + duration); } - if (hasAnyFlag(FLAG_TASKBAR_HIDDEN)) { - iconAlignAnim.setInterpolator(FINAL_FRAME); - } else { - animatorSet.play(iconAlignAnim); + if (!isPinnedTaskbar) { + if (hasAnyFlag(FLAG_TASKBAR_HIDDEN)) { + iconAlignAnim.setInterpolator(FINAL_FRAME); + } else { + animatorSet.play(iconAlignAnim); + } } } - Interpolator interpolator = enableScalingRevealHomeAnimation() + Interpolator interpolator = enableScalingRevealHomeAnimation() && !isPinnedTaskbar ? ScalingWorkspaceRevealAnim.SCALE_INTERPOLATOR : EMPHASIZED; + animatorSet.setInterpolator(interpolator); if (start) { @@ -688,6 +714,49 @@ public class TaskbarLauncherStateController { return animatorSet; } + private void setupPinnedTaskbarAnimation(AnimatorSet animatorSet, boolean showTaskbar, + AnimatedFloat taskbarBgOffset, float taskbarBgOffsetStart, float taskbarBgOffsetEnd, + long duration, Animator taskbarBackgroundAlpha) { + float targetAlpha = !showTaskbar ? 1 : 0; + mLauncher.getHotseat().setIconsAlpha(targetAlpha, ALPHA_CHANNEL_TASKBAR_ALIGNMENT); + if (mIsQsbInline) { + mLauncher.getHotseat().setQsbAlpha(targetAlpha, + ALPHA_CHANNEL_TASKBAR_ALIGNMENT); + } + + if ((taskbarBgOffset.value != taskbarBgOffsetEnd && !taskbarBgOffset.isAnimating()) + || taskbarBgOffset.isAnimatingToValue(taskbarBgOffsetStart)) { + taskbarBgOffset.cancelAnimation(); + Animator taskbarIconAlpha = mTaskbarAlphaForHome.animateToValue( + showTaskbar ? 1f : 0f); + AnimatedFloat taskbarIconTranslationYForHome = + mControllers.taskbarViewController.mTaskbarIconTranslationYForHome; + ObjectAnimator taskbarBackgroundOffset = taskbarBgOffset.animateToValue( + taskbarBgOffsetStart, + taskbarBgOffsetEnd); + ObjectAnimator taskbarIconsYTranslation = null; + float taskbarHeight = + mControllers.taskbarActivityContext.getDeviceProfile().taskbarHeight; + if (showTaskbar) { + taskbarIconsYTranslation = taskbarIconTranslationYForHome.animateToValue( + taskbarHeight, 0); + } else { + taskbarIconsYTranslation = taskbarIconTranslationYForHome.animateToValue(0, + taskbarHeight); + } + + taskbarIconAlpha.setDuration(duration); + taskbarIconsYTranslation.setDuration(duration); + taskbarBackgroundOffset.setDuration(duration); + + animatorSet.play(taskbarIconAlpha); + animatorSet.play(taskbarIconsYTranslation); + animatorSet.play(taskbarBackgroundOffset); + } + taskbarBackgroundAlpha.setInterpolator(showTaskbar ? INSTANT : FINAL_FRAME); + taskbarBackgroundAlpha.setDuration(duration); + } + /** * Whether the taskbar is aligned with the hotseat in the current/target launcher state. * @@ -950,8 +1019,9 @@ public class TaskbarLauncherStateController { * * @param finishedToApp {@code true} if the recents animation finished to showing an app and * not workspace or overview - * @param canceled {@code true} if the recents animation was canceled instead of finishing - * to completion + * @param canceled {@code true} if the recents animation was canceled instead of + * finishing + * to completion */ private void endGestureStateOverride(boolean finishedToApp, boolean canceled) { mCallbacks.removeListener(this); @@ -968,6 +1038,7 @@ public class TaskbarLauncherStateController { /** * Updates the visible state immediately to ensure a seamless handoff. + * * @param finishedToApp True iff user is in an app. */ private void updateStateForUserFinishedToApp(boolean finishedToApp) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index c1dd216a9c..67be8dac05 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -23,6 +23,7 @@ import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; import static com.android.internal.jank.InteractionJankMonitor.Configuration; import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation; +import static com.android.launcher3.QuickstepTransitionManager.PINNED_TASKBAR_TRANSITION_DURATION; import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW; @@ -398,6 +399,9 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba * Returns how long the stash/unstash animation should play. */ public long getStashDuration() { + if (DisplayController.isPinnedTaskbar(mActivity)) { + return PINNED_TASKBAR_TRANSITION_DURATION; + } return DisplayController.isTransientTaskbar(mActivity) ? TRANSIENT_TASKBAR_STASH_DURATION : TASKBAR_STASH_DURATION; diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index cebabffa75..bb4f07a72f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -120,7 +120,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private final TaskbarView mTaskbarView; private final MultiValueAlpha mTaskbarIconAlpha; private final AnimatedFloat mTaskbarIconScaleForStash = new AnimatedFloat(this::updateScale); - private final AnimatedFloat mTaskbarIconTranslationYForHome = new AnimatedFloat( + public final AnimatedFloat mTaskbarIconTranslationYForHome = new AnimatedFloat( this::updateTranslationY); private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat( this::updateTranslationY); @@ -796,6 +796,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar */ private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) { PendingAnimation setter = new PendingAnimation(100); + // icon alignment not needed for pinned taskbar. + if (DisplayController.isPinnedTaskbar(mActivity)) return setter.createPlaybackController(); mOnControllerPreCreateCallback.run(); DeviceProfile taskbarDp = mActivity.getDeviceProfile(); Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity); diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index 3a39cf28b1..8ad00bfd88 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -95,6 +95,7 @@ public class QuickstepAtomicAnimationFactory extends public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState, StateAnimationConfig config) { RecentsView overview = mContainer.getOverviewPanel(); + boolean isPinnedTaskbar = DisplayController.isPinnedTaskbar(mContainer); if ((fromState == OVERVIEW || fromState == OVERVIEW_SPLIT_SELECT) && toState == NORMAL) { overview.switchToScreenshot(() -> overview.finishRecentsAnimation(true /* toRecents */, null)); @@ -109,7 +110,8 @@ public class QuickstepAtomicAnimationFactory extends // We sync the scrim fade with the taskbar animation duration to avoid any flickers for // taskbar icons disappearing before hotseat icons show up. float scrimUpperBoundFromSplit = - QuickstepTransitionManager.getTaskbarToHomeDuration() / (float) config.duration; + QuickstepTransitionManager.getTaskbarToHomeDuration(isPinnedTaskbar) + / (float) config.duration; scrimUpperBoundFromSplit = Math.min(scrimUpperBoundFromSplit, 1f); config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR, 0, 0.25f)); config.setInterpolator(ANIM_SCRIM_FADE, @@ -139,7 +141,8 @@ public class QuickstepAtomicAnimationFactory extends // Sync scroll so that it ends before or at the same time as the taskbar animation. if (mContainer.getDeviceProfile().isTaskbarPresent) { config.duration = Math.min( - config.duration, QuickstepTransitionManager.getTaskbarToHomeDuration()); + config.duration, + QuickstepTransitionManager.getTaskbarToHomeDuration(isPinnedTaskbar)); } overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration)); } else { diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 97d71799fd..ff31eac913 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -100,6 +100,7 @@ import com.android.internal.jank.Cuj; import com.android.internal.util.LatencyTracker; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; @@ -1373,8 +1374,9 @@ public abstract class AbsSwipeUpHandler< mInputConsumerProxy.enable(); } if (endTarget == HOME) { + boolean isPinnedTaskbar = DisplayController.isPinnedTaskbar(mContext); duration = mContainer != null && mContainer.getDeviceProfile().isTaskbarPresent - ? StaggeredWorkspaceAnim.DURATION_TASKBAR_MS + ? QuickstepTransitionManager.getTaskbarToHomeDuration(isPinnedTaskbar) : StaggeredWorkspaceAnim.DURATION_MS; ContextualEduStatsManager.INSTANCE.get(mContext).updateEduStats( mGestureState.isTrackpadGesture(), GestureType.HOME); diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java index 997a842dc2..12ca25702e 100644 --- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java +++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java @@ -49,6 +49,7 @@ import com.android.launcher3.celllayout.CellLayoutLayoutParams; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.uioverrides.QuickstepLauncher; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DynamicResource; import com.android.quickstep.views.RecentsView; import com.android.systemui.plugins.ResourceProvider; @@ -63,8 +64,7 @@ public class StaggeredWorkspaceAnim { private static final int APP_CLOSE_ROW_START_DELAY_MS = 10; // Should be used for animations running alongside this StaggeredWorkspaceAnim. public static final int DURATION_MS = 250; - public static final int DURATION_TASKBAR_MS = - QuickstepTransitionManager.getTaskbarToHomeDuration(); + private final int mTaskbarDurationInMs; private static final float MAX_VELOCITY_PX_PER_S = 22f; @@ -81,6 +81,8 @@ public class StaggeredWorkspaceAnim { public StaggeredWorkspaceAnim(QuickstepLauncher launcher, float velocity, boolean animateOverviewScrim, @Nullable View ignoredView, boolean staggerWorkspace) { + mTaskbarDurationInMs = QuickstepTransitionManager.getTaskbarToHomeDuration( + DisplayController.isPinnedTaskbar(launcher)); prepareToAnimate(launcher, animateOverviewScrim); mIgnoredView = ignoredView; @@ -93,7 +95,7 @@ public class StaggeredWorkspaceAnim { .getDimensionPixelSize(R.dimen.swipe_up_max_workspace_trans_y); DeviceProfile grid = launcher.getDeviceProfile(); - long duration = grid.isTaskbarPresent ? DURATION_TASKBAR_MS : DURATION_MS; + long duration = grid.isTaskbarPresent ? mTaskbarDurationInMs : DURATION_MS; if (staggerWorkspace) { Workspace workspace = launcher.getWorkspace(); Hotseat hotseat = launcher.getHotseat(); diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt index 71f4ef4ee6..5e438bd8e1 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt @@ -21,6 +21,7 @@ import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING +import com.android.launcher3.QuickstepTransitionManager.PINNED_TASKBAR_TRANSITION_DURATION import com.android.launcher3.R import com.android.launcher3.taskbar.StashedHandleViewController.ALPHA_INDEX_STASHED import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN @@ -158,7 +159,7 @@ class TaskbarStashControllerTest { @Test @TaskbarMode(PINNED) fun testGetStashDuration_pinnedMode() { - assertThat(stashController.stashDuration).isEqualTo(TASKBAR_STASH_DURATION) + assertThat(stashController.stashDuration).isEqualTo(PINNED_TASKBAR_TRANSITION_DURATION) } @Test