If RecentsView is empty when starting quickswitch, listen for tasks to load

When first doing quick switch, RecentsView might be empty but tasks subsequently
load. In that case, we can update our animators to have the correct scale etc.

Test: From home, toggle dark theme or RTL from quick setting tiles,
then quick switch; ensure RecentsView comes in scaled up.

Bug: 126596417
Change-Id: I28d79455431b1da634372d6f31182406aa24cd06
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 613386e..4e08df9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -98,6 +98,7 @@
     private final float mYRange;
     private final MotionPauseDetector mMotionPauseDetector;
     private final float mMotionPauseMinDisplacement;
+    private final LauncherRecentsView mRecentsView;
 
     private boolean mNoIntercept;
     private LauncherState mStartState;
@@ -119,6 +120,7 @@
         mMotionPauseDetector = new MotionPauseDetector(mLauncher);
         mMotionPauseMinDisplacement = mLauncher.getResources().getDimension(
                 R.dimen.motion_pause_detector_min_displacement_from_app);
+        mRecentsView = mLauncher.getOverviewPanel();
     }
 
     @Override
@@ -208,6 +210,15 @@
         updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder, ANIM_ALL);
         mNonOverviewAnim.dispatchOnStart();
 
+        if (mRecentsView.getTaskViewCount() == 0) {
+            mRecentsView.setOnEmptyMessageUpdatedListener(isEmpty -> {
+                if (!isEmpty && mSwipeDetector.isDraggingState()) {
+                    // We have loaded tasks, update the animators to start at the correct scale etc.
+                    setupOverviewAnimators();
+                }
+            });
+        }
+
         setupOverviewAnimators();
     }
 
@@ -228,25 +239,25 @@
         LauncherState.ScaleAndTranslation toScaleAndTranslation = toState
                 .getOverviewScaleAndTranslation(mLauncher);
         // Update RecentView's translationX to have it start offscreen.
-        LauncherRecentsView recentsView = mLauncher.getOverviewPanel();
         float startScale = Utilities.mapRange(
                 SCALE_DOWN_INTERPOLATOR.getInterpolation(Y_ANIM_MIN_PROGRESS),
                 fromScaleAndTranslation.scale,
                 toScaleAndTranslation.scale);
-        fromScaleAndTranslation.translationX = recentsView.getOffscreenTranslationX(startScale);
+        fromScaleAndTranslation.translationX = mRecentsView.getOffscreenTranslationX(startScale);
 
         // Set RecentView's initial properties.
-        recentsView.setScaleX(fromScaleAndTranslation.scale);
-        recentsView.setScaleY(fromScaleAndTranslation.scale);
-        recentsView.setTranslationX(fromScaleAndTranslation.translationX);
-        recentsView.setTranslationY(fromScaleAndTranslation.translationY);
-        recentsView.setContentAlpha(1);
+        mRecentsView.setScaleX(fromScaleAndTranslation.scale);
+        mRecentsView.setScaleY(fromScaleAndTranslation.scale);
+        mRecentsView.setTranslationX(fromScaleAndTranslation.translationX);
+        mRecentsView.setTranslationY(fromScaleAndTranslation.translationY);
+        mRecentsView.setContentAlpha(1);
+        mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress());
 
         // As we drag right, animate the following properties:
         //   - RecentsView translationX
         //   - OverviewScrim
         AnimatorSet xOverviewAnim = new AnimatorSet();
-        xOverviewAnim.play(ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_X,
+        xOverviewAnim.play(ObjectAnimator.ofFloat(mRecentsView, View.TRANSLATION_X,
                 toScaleAndTranslation.translationX));
         xOverviewAnim.play(ObjectAnimator.ofFloat(
                 mLauncher.getDragLayer().getOverviewScrim(), OverviewScrim.SCRIM_PROGRESS,
@@ -261,11 +272,11 @@
         //   - RecentsView scale
         //   - RecentsView fullscreenProgress
         AnimatorSet yAnimation = new AnimatorSet();
-        Animator translateYAnim = ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_Y,
+        Animator translateYAnim = ObjectAnimator.ofFloat(mRecentsView, View.TRANSLATION_Y,
                 toScaleAndTranslation.translationY);
-        Animator scaleAnim = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY,
+        Animator scaleAnim = ObjectAnimator.ofFloat(mRecentsView, SCALE_PROPERTY,
                 toScaleAndTranslation.scale);
-        Animator fullscreenProgressAnim = ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS,
+        Animator fullscreenProgressAnim = ObjectAnimator.ofFloat(mRecentsView, FULLSCREEN_PROGRESS,
                 fromState.getOverviewFullscreenProgress(), toState.getOverviewFullscreenProgress());
         scaleAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
         fullscreenProgressAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
@@ -466,5 +477,6 @@
         mYOverviewAnim = null;
         mIsHomeScreenVisible = true;
         mSwipeDetector.finishedScrolling();
+        mRecentsView.setOnEmptyMessageUpdatedListener(null);
     }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index c836791..cb20ed0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -309,6 +309,7 @@
     private final Point mLastMeasureSize = new Point();
     private final int mEmptyMessagePadding;
     private boolean mShowEmptyMessage;
+    private OnEmptyMessageUpdatedListener mOnEmptyMessageUpdatedListener;
     private Layout mEmptyTextLayout;
     private boolean mLiveTileOverlayAttached;
 
@@ -1456,6 +1457,10 @@
         return null;
     }
 
+    public void setOnEmptyMessageUpdatedListener(OnEmptyMessageUpdatedListener listener) {
+        mOnEmptyMessageUpdatedListener = listener;
+    }
+
     public void updateEmptyMessage() {
         boolean isEmpty = getTaskViewCount() == 0;
         boolean hasSizeChanged = mLastMeasureSize.x != getWidth()
@@ -1467,6 +1472,10 @@
         mShowEmptyMessage = isEmpty;
         updateEmptyStateUi(hasSizeChanged);
         invalidate();
+
+        if (mOnEmptyMessageUpdatedListener != null) {
+            mOnEmptyMessageUpdatedListener.onEmptyMessageUpdated(mShowEmptyMessage);
+        }
     }
 
     @Override
@@ -1927,4 +1936,15 @@
         return !(view instanceof TaskView) && !(view instanceof ClearAllButton)
                 && index <= mTaskViewStartIndex;
     }
+
+    /**
+     * Used to register callbacks for when our empty message state changes.
+     *
+     * @see #setOnEmptyMessageUpdatedListener(OnEmptyMessageUpdatedListener)
+     * @see #updateEmptyMessage()
+     */
+    public interface OnEmptyMessageUpdatedListener {
+        /** @param isEmpty Whether RecentsView is empty (i.e. has no children) */
+        void onEmptyMessageUpdated(boolean isEmpty);
+    }
 }