Merge "Animate in desktop app select toast" into udc-qpr-dev
diff --git a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
index 45a26a5..a5be142 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
@@ -15,16 +15,24 @@
  */
 package com.android.quickstep.views;
 
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
 import static com.android.app.animation.Interpolators.LINEAR;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.LinearLayout;
 
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 
 /**
  * Floating view show on launcher home screen that notifies the user that an app will be launched to
@@ -32,13 +40,21 @@
  */
 public class DesktopAppSelectView extends LinearLayout {
 
+    private static final int SHOW_INITIAL_HEIGHT_DP = 7;
+    private static final int SHOW_CONTAINER_SCALE_DURATION = 333;
+    private static final int SHOW_CONTAINER_ALPHA_DURATION = 83;
+    private static final int SHOW_CONTENT_ALPHA_DELAY = 67;
+    private static final int SHOW_CONTENT_ALPHA_DURATION = 83;
     private static final int HIDE_DURATION = 83;
 
     private final Launcher mLauncher;
 
+    private View mText;
+    private View mCloseButton;
     @Nullable
-    private Runnable mOnCloseCallback = null;
-    private boolean mIsHideAnimationRunning;
+    private Runnable mOnCloseCallback;
+    private AnimatorSet mShowAnimation;
+    private Animator mHideAnimation;
 
     public DesktopAppSelectView(Context context) {
         this(context, null);
@@ -68,15 +84,17 @@
         DesktopAppSelectView view = (DesktopAppSelectView) launcher.getLayoutInflater().inflate(
                 R.layout.floating_desktop_app_select, launcher.getDragLayer(), false);
         view.setOnCloseClickCallback(onCloseCallback);
-        launcher.getDragLayer().addView(view);
+        view.show();
         return view;
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        findViewById(R.id.close_button).setOnClickListener(v -> {
-            if (!mIsHideAnimationRunning) {
+        mText = findViewById(R.id.desktop_app_select_text);
+        mCloseButton = findViewById(R.id.close_button);
+        mCloseButton.setOnClickListener(v -> {
+            if (mHideAnimation == null) {
                 hide();
                 if (mOnCloseCallback != null) {
                     mOnCloseCallback.run();
@@ -85,18 +103,71 @@
         });
     }
 
+    private void show() {
+        mLauncher.getDragLayer().addView(this);
+
+        // Set up initial values
+        getBackground().setAlpha(0);
+        mText.setAlpha(0);
+        mCloseButton.setAlpha(0);
+        int initialHeightPx = Utilities.dpToPx(SHOW_INITIAL_HEIGHT_DP);
+        int finalHeight = getResources().getDimensionPixelSize(
+                R.dimen.desktop_mode_floating_app_select_height);
+        float initialScale = initialHeightPx / (float) finalHeight;
+        setScaleY(initialScale);
+        setPivotY(0);
+
+        // Animate the container
+        ValueAnimator containerBackground = ValueAnimator.ofInt(0, 255);
+        containerBackground.addUpdateListener(
+                animation -> getBackground().setAlpha((Integer) animation.getAnimatedValue()));
+        containerBackground.setDuration(SHOW_CONTAINER_ALPHA_DURATION);
+        containerBackground.setInterpolator(LINEAR);
+
+        ObjectAnimator containerSize = ObjectAnimator.ofFloat(this, SCALE_Y, 1f);
+        containerSize.setDuration(SHOW_CONTAINER_SCALE_DURATION);
+        containerSize.setInterpolator(EMPHASIZED_DECELERATE);
+
+        // Animate the contents
+        ObjectAnimator textAlpha = ObjectAnimator.ofFloat(mText, ALPHA, 1);
+        ObjectAnimator buttonAlpha = ObjectAnimator.ofFloat(mCloseButton, ALPHA, 1);
+        AnimatorSet contentAlpha = new AnimatorSet();
+        contentAlpha.playTogether(textAlpha, buttonAlpha);
+        contentAlpha.setStartDelay(SHOW_CONTENT_ALPHA_DELAY);
+        contentAlpha.setDuration(SHOW_CONTENT_ALPHA_DURATION);
+        contentAlpha.setInterpolator(LINEAR);
+
+        // Start the animation
+        mShowAnimation = new AnimatorSet();
+        mShowAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                mShowAnimation = null;
+            }
+        });
+        mShowAnimation.playTogether(containerBackground, containerSize, contentAlpha);
+        mShowAnimation.start();
+    }
+
     /**
      * Hide the floating view
      */
     public void hide() {
-        if (!mIsHideAnimationRunning) {
-            mIsHideAnimationRunning = true;
-            animate().alpha(0).setDuration(HIDE_DURATION).setInterpolator(LINEAR).withEndAction(
-                    () -> {
-                        mLauncher.getDragLayer().removeView(this);
-                        mIsHideAnimationRunning = false;
-                    });
+        if (mShowAnimation != null) {
+            mShowAnimation.cancel();
         }
+        mHideAnimation = ObjectAnimator.ofFloat(this, ALPHA, 0);
+        mHideAnimation.setDuration(HIDE_DURATION).setInterpolator(LINEAR);
+        mHideAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                mLauncher.getDragLayer().removeView(DesktopAppSelectView.this);
+                mHideAnimation = null;
+            }
+        });
+        mHideAnimation.start();
     }
 
     /**