Merge "Taskbar motion polish to keep icons within taskbar bg bounds." into tm-qpr-dev am: 8a53e78f22

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/22133846

Change-Id: I1ede6c749f24762727fbf7dc8ae1085a70ab0bc3
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index a1c9744..7d5a400 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.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 @@
     /** 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 @@
 
     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 @@
                         + " -> " + 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 c9553e3..4d92a9e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -90,9 +90,6 @@
     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 @@
     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 @@
                     }, VERTICAL);
             mSwipeDownDetector.setDetectableScrollConditions(DIRECTION_NEGATIVE, false);
         }
+        mIsRtl = Utilities.isRtl(mTaskbarView.getResources());
     }
 
     public void init(TaskbarControllers controllers) {
@@ -309,18 +309,34 @@
                 ));
     }
 
-    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 @@
         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 @@
 
                 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);