Fade to empty view when no tasks for Recents Go

This CL adds a view for when there are no tasks and fades into/out of it
appropriately based off changes to the adapter.

Bug: 114136250
Test: Add task, remove task, see empty view shows up properly.
Change-Id: I47d0bbfb19d56f5f0de5bec3c0ac2b5cfb63253f
diff --git a/go/quickstep/res/layout/icon_recents_root_view.xml b/go/quickstep/res/layout/icon_recents_root_view.xml
index 6c50950..ff3dcef9 100644
--- a/go/quickstep/res/layout/icon_recents_root_view.xml
+++ b/go/quickstep/res/layout/icon_recents_root_view.xml
@@ -24,5 +24,15 @@
         android:id="@+id/recent_task_recycler_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:scrollbars="none"/>
+        android:scrollbars="none"
+        android:visibility="gone"/>
+    <TextView
+        android:id="@+id/recent_task_empty_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="@string/recents_empty_message"
+        android:textColor="@android:color/white"
+        android:textSize="25sp"
+        android:visibility="gone"/>
 </com.android.quickstep.views.IconRecentsView>
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index b7740eb..8c7177b 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -17,15 +17,19 @@
 
 import static androidx.recyclerview.widget.LinearLayoutManager.VERTICAL;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
+import android.view.View;
 import android.view.ViewDebug;
 import android.widget.FrameLayout;
 
 import androidx.recyclerview.widget.ItemTouchHelper;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver;
 
 import com.android.launcher3.R;
 import com.android.quickstep.TaskAdapter;
@@ -70,6 +74,7 @@
                     return ALPHA.get(view);
                 }
             };
+    private static final long CROSSFADE_DURATION = 300;
 
     /**
      * A ratio representing the view's relative placement within its padded space. For example, 0
@@ -84,7 +89,7 @@
 
     private float mTranslationYFactor;
     private RecyclerView mTaskRecyclerView;
-
+    private View mEmptyView;
 
     public IconRecentsView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -106,6 +111,19 @@
             ItemTouchHelper helper = new ItemTouchHelper(
                     new TaskSwipeCallback(mTaskInputController));
             helper.attachToRecyclerView(mTaskRecyclerView);
+
+            mEmptyView = findViewById(R.id.recent_task_empty_view);
+            mTaskAdapter.registerAdapterDataObserver(new AdapterDataObserver() {
+                @Override
+                public void onChanged() {
+                    updateContentViewVisibility();
+                }
+
+                @Override
+                public void onItemRangeRemoved(int positionStart, int itemCount) {
+                    updateContentViewVisibility();
+                }
+            });
         }
     }
 
@@ -133,4 +151,44 @@
     private float computeTranslationYForFactor(float translationYFactor) {
         return translationYFactor * (getPaddingBottom() - getPaddingTop());
     }
+
+    /**
+     * Update the content view so that the appropriate view is shown based off the current list
+     * of tasks.
+     */
+    private void updateContentViewVisibility() {
+        int taskListSize = mTaskLoader.getCurrentTaskList().size();
+        if (mEmptyView.getVisibility() != VISIBLE && taskListSize == 0) {
+            crossfadeViews(mEmptyView, mTaskRecyclerView);
+            // TODO: Go to home.
+        }
+        if (mTaskRecyclerView.getVisibility() != VISIBLE && taskListSize > 0) {
+            crossfadeViews(mTaskRecyclerView, mEmptyView);
+        }
+    }
+
+    /**
+     * Animate views so that one view fades in while the other fades out.
+     *
+     * @param fadeInView view that should fade in
+     * @param fadeOutView view that should fade out
+     */
+    private void crossfadeViews(View fadeInView, View fadeOutView) {
+        fadeInView.setVisibility(VISIBLE);
+        fadeInView.setAlpha(0f);
+        fadeInView.animate()
+                .alpha(1f)
+                .setDuration(CROSSFADE_DURATION)
+                .setListener(null);
+
+        fadeOutView.animate()
+                .alpha(0f)
+                .setDuration(CROSSFADE_DURATION)
+                .setListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        fadeOutView.setVisibility(GONE);
+                    }
+                });
+    }
 }