diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index a1c9744b66..7d5a400f13 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -39,7 +39,6 @@ import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; -import com.android.launcher3.util.window.RefreshRateTracker; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationController; import com.android.quickstep.views.RecentsView; @@ -67,6 +66,10 @@ import java.util.StringJoiner; /** Equivalent to an int with all 1s for binary operation purposes */ private static final int FLAGS_ALL = ~0; + private static final float TASKBAR_BG_ALPHA_LAUNCHER_NOT_ALIGNED_DELAY_MULT = 0.33f; + private static final float TASKBAR_BG_ALPHA_NOT_LAUNCHER_NOT_ALIGNED_DELAY_MULT = 0.33f; + private static final float TASKBAR_BG_ALPHA_LAUNCHER_IS_ALIGNED_DURATION_MULT = 0.25f; + private final AnimatedFloat mIconAlignment = new AnimatedFloat(this::onIconAlignmentRatioChanged); @@ -274,7 +277,8 @@ import java.util.StringJoiner; private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) { final boolean goingToLauncher = isInLauncher(); - final float toAlignment = isIconAlignedWithHotseat() ? 1 : 0; + final boolean isIconAlignedWithHotseat = isIconAlignedWithHotseat(); + final float toAlignment = isIconAlignedWithHotseat ? 1 : 0; boolean handleOpenFloatingViews = false; if (DEBUG) { Log.d(TAG, "onStateChangeApplied - mState: " + getStateString(mState) @@ -343,15 +347,29 @@ import java.util.StringJoiner; + " -> " + backgroundAlpha + ": " + duration); } + boolean goingToLauncherIconNotAligned = goingToLauncher && !isIconAlignedWithHotseat; + boolean notGoingToLauncherIconNotAligned = !goingToLauncher + && !isIconAlignedWithHotseat; + boolean goingToLauncherIconIsAligned = goingToLauncher && isIconAlignedWithHotseat; + + 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 (goingToLauncherIconNotAligned) { + startDelay = duration * TASKBAR_BG_ALPHA_LAUNCHER_NOT_ALIGNED_DELAY_MULT; + } else if (notGoingToLauncherIconNotAligned) { + startDelay = duration * TASKBAR_BG_ALPHA_NOT_LAUNCHER_NOT_ALIGNED_DELAY_MULT; + } + float newDuration = duration - startDelay; + if (goingToLauncherIconIsAligned) { + // 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(duration); - // Add a single frame delay to the taskbar bg to avoid too many moving parts during the - // app launch animation. - taskbarBackgroundAlpha.setStartDelay( - (hasAnyFlag(changedFlags, FLAG_RESUMED) && !goingToLauncher) - ? RefreshRateTracker.getSingleFrameMs(mLauncher) - : 0); + .setDuration((long) newDuration); + taskbarBackgroundAlpha.setStartDelay((long) startDelay); animatorSet.play(taskbarBackgroundAlpha); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index c9553e3d97..4d92a9e36f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -90,9 +90,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar public static final int ALPHA_INDEX_SMALL_SCREEN = 6; private static final int NUM_ALPHA_CHANNELS = 7; - // This allows the icons on the edge to stay within the taskbar background bounds. - private static final float ICON_REVEAL_X_DURATION_MULTIPLIER = 0.8f; - private static final float TASKBAR_DARK_THEME_ICONS_BACKGROUND_LUMINANCE = 0.30f; private final TaskbarActivityContext mActivity; @@ -134,6 +131,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private final DeviceProfile.OnDeviceProfileChangeListener mDeviceProfileChangeListener = dp -> commitRunningAppsToUI(); + private final boolean mIsRtl; + public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) { mActivity = activity; mTaskbarView = taskbarView; @@ -180,6 +179,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar }, VERTICAL); mSwipeDownDetector.setDetectableScrollConditions(DIRECTION_NEGATIVE, false); } + mIsRtl = Utilities.isRtl(mTaskbarView.getResources()); } public void init(TaskbarControllers controllers) { @@ -309,18 +309,34 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar )); } - private ValueAnimator createRevealAnimForView(View view, boolean isStashed) { + private ValueAnimator createRevealAnimForView(View view, boolean isStashed, float newWidth, + boolean shouldStartAlign) { Rect viewBounds = new Rect(0, 0, view.getWidth(), view.getHeight()); int centerY = viewBounds.centerY(); int halfHandleHeight = mStashedHandleHeight / 2; + final int top = centerY - halfHandleHeight; + final int bottom = centerY + halfHandleHeight; - Rect stashedRect = new Rect(viewBounds.left, - centerY - halfHandleHeight, - viewBounds.right, - centerY + halfHandleHeight); + final int left; + final int right; + if (shouldStartAlign) { + if (mIsRtl) { + right = viewBounds.right; + left = (int) (right - newWidth); + } else { + left = viewBounds.left; + right = (int) (left + newWidth); + } + } else { + int widthDelta = (int) ((viewBounds.width() - newWidth) / 2); + left = viewBounds.left + widthDelta; + right = viewBounds.right - widthDelta; + } + + Rect stashedRect = new Rect(left, top, right, bottom); float radius = 0; - float stashedRadius = viewBounds.width() / 2f; + float stashedRadius = stashedRect.width() / 2f; return new RoundedRectRevealOutlineProvider(radius, stashedRadius, viewBounds, stashedRect) .createRevealAnimator(view, !isStashed, 0); @@ -342,44 +358,36 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar Rect stashedBounds = new Rect(); mControllers.stashedHandleViewController.getStashedHandleBounds(stashedBounds); - boolean isQsbInline = mActivity.getDeviceProfile().isQsbInline; - int numIcons = mTaskbarView.getChildCount() - (isQsbInline ? 1 : 0); - // We do not actually modify the width of the icons, but we will use this width to position - // the children to overlay the nav handle. - float virtualChildWidth = stashedBounds.width() / (float) numIcons; + int numIcons = mTaskbarView.getChildCount(); + float newChildWidth = stashedBounds.width() / (float) numIcons; // All children move the same y-amount since they will be cropped to the same centerY. float croppedTransY = mTaskbarView.getIconTouchSize() - stashedBounds.height(); - boolean isRtl = Utilities.isRtl(mTaskbarView.getResources()); for (int i = mTaskbarView.getChildCount() - 1; i >= 0; i--) { View child = mTaskbarView.getChildAt(i); boolean isQsb = child == mTaskbarView.getQsb(); // Crop the icons to/from the nav handle shape. - reveal.play(createRevealAnimForView(child, isStashed).setDuration(duration)); + reveal.play(createRevealAnimForView(child, isStashed, newChildWidth, isQsb) + .setDuration(duration)); // Translate the icons to/from their locations as the "nav handle." - // We look at 'left' and 'right' values to ensure that the children stay within the - // bounds of the stashed handle. // All of the Taskbar icons will overlap the entirety of the stashed handle // And the QSB, if inline, will overlap part of stashed handle as well. - int positionInHandle = (isQsbInline && !isQsb) - ? i + (isRtl ? 1 : -1) - : i; float currentPosition = isQsb ? child.getX() : child.getLeft(); - float newPosition = stashedBounds.left + (virtualChildWidth * positionInHandle); + float newPosition = stashedBounds.left + (newChildWidth * i); final float croppedTransX; + // We look at 'left' and 'right' values to ensure that the children stay within the + // bounds of the stashed handle since the new width only occurs at the end of the anim. if (currentPosition > newPosition) { - float newRight = stashedBounds.right - (virtualChildWidth - * (numIcons - 1 - positionInHandle)); + float newRight = stashedBounds.right - (newChildWidth + * (numIcons - 1 - i)); croppedTransX = -(currentPosition + child.getWidth() - newRight); } else { croppedTransX = newPosition - currentPosition; } - - long transXDuration = (long) (duration * ICON_REVEAL_X_DURATION_MULTIPLIER); float[] transX = isStashed ? new float[] {croppedTransX} : new float[] {croppedTransX, 0}; @@ -392,14 +400,14 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar reveal.play(ObjectAnimator.ofFloat(mtd.getTranslationX(INDEX_TASKBAR_REVEAL_ANIM), MULTI_PROPERTY_VALUE, transX) - .setDuration(transXDuration)); + .setDuration(duration)); reveal.play(ObjectAnimator.ofFloat(mtd.getTranslationY(INDEX_TASKBAR_REVEAL_ANIM), MULTI_PROPERTY_VALUE, transY)); as.addListener(forEndCallback(() -> mtd.setTranslation(INDEX_TASKBAR_REVEAL_ANIM, 0, 0))); } else { reveal.play(ObjectAnimator.ofFloat(child, VIEW_TRANSLATE_X, transX) - .setDuration(transXDuration)); + .setDuration(duration)); reveal.play(ObjectAnimator.ofFloat(child, VIEW_TRANSLATE_Y, transY)); as.addListener(forEndCallback(() -> { child.setTranslationX(0);