Smoother folder animation tweaks.

1. Start preview item animations later opening
2. Finish item animations sooner when closing
3. 1 & 2 allow the preview items to move as part of
   the Folder and allows for a smoother animation
4. Remove setCurrentPlayTime as it is O API.

Bug: 36522198
Bug: 35064148
Change-Id: If63d4d032078ff4e28b72a09e35da3a71f1d0e27
diff --git a/res/interpolator/folder_preview_item_closing_interpolator.xml b/res/interpolator/folder_preview_item_closing_interpolator.xml
index 1d77081..d8ddb0c 100644
--- a/res/interpolator/folder_preview_item_closing_interpolator.xml
+++ b/res/interpolator/folder_preview_item_closing_interpolator.xml
@@ -18,7 +18,7 @@
 -->
 
 <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:controlX1="1"
+    android:controlX1="0.5"
     android:controlY1="0"
     android:controlX2="1"
     android:controlY2="0"/>
diff --git a/res/values/config.xml b/res/values/config.xml
index 745bce3..4c19dec 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -58,6 +58,7 @@
     <integer name="config_folderExpandDuration">120</integer>
     <integer name="config_materialFolderExpandDuration">200</integer>
     <integer name="config_materialFolderExpandStagger">60</integer>
+    <integer name="config_folderDelay">30</integer>
 
     <!-- The distance at which the animation should take the max duration -->
     <integer name="config_dropAnimMaxDist">800</integer>
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index bce13bc..20c2612 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.support.v4.os.BuildCompat;
 import android.text.InputType;
 import android.text.Selection;
 import android.util.AttributeSet;
@@ -518,7 +519,9 @@
         long startTime = 0;
         if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
             // This allows a nice transition when closing a Folder while it is still animating open.
-            startTime = mCurrentAnimator.getDuration() - mCurrentAnimator.getCurrentPlayTime();
+            if (BuildCompat.isAtLeastO()) {
+                startTime = mCurrentAnimator.getDuration() - mCurrentAnimator.getCurrentPlayTime();
+            }
             mCurrentAnimator.cancel();
         }
         a.addListener(new AnimatorListenerAdapter() {
@@ -533,7 +536,9 @@
                 mCurrentAnimator = null;
             }
         });
-        a.setCurrentPlayTime(startTime);
+        if (BuildCompat.isAtLeastO()) {
+            a.setCurrentPlayTime(startTime);
+        }
         a.start();
     }
 
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index c1c974c..a62d1b7 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -64,6 +64,9 @@
 
     private final boolean mIsOpening;
 
+    private final int mDuration;
+    private final int mDelay;
+
     private final TimeInterpolator mOpeningInterpolator;
     private final TimeInterpolator mClosingInterpolator;
     private final TimeInterpolator mPreviewItemOpeningInterpolator;
@@ -116,6 +119,9 @@
 
         mIsOpening = isOpening;
 
+        mDuration = mFolder.mMaterialExpandDuration;
+        mDelay = mContext.getResources().getInteger(R.integer.config_folderDelay);
+
         mOpeningInterpolator = AnimationUtils.loadInterpolator(mContext,
                 R.interpolator.folder_opening_interpolator);
         mClosingInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -194,14 +200,13 @@
 
         // Create the animators.
         AnimatorSet a = LauncherAnimUtils.createAnimatorSet();
-        a.setDuration(mFolder.mMaterialExpandDuration);
 
-        a.play(getAnimator(mFolder, View.TRANSLATION_X, xDistance, 0f));
-        a.play(getAnimator(mFolder, View.TRANSLATION_Y, yDistance, 0f));
-        a.play(getAnimator(mFolder, SCALE_PROPERTY, initialScale, finalScale));
-        a.play(getAnimator(items, ITEMS_TEXT_COLOR_PROPERTY, Color.TRANSPARENT, finalTextColor));
-        a.play(getAnimator(mFolderBackground, "color", initialColor, finalColor));
-        a.play(new RoundedRectRevealOutlineProvider(initialSize / 2f, finalRadius, startRect,
+        play(a, getAnimator(mFolder, View.TRANSLATION_X, xDistance, 0f));
+        play(a, getAnimator(mFolder, View.TRANSLATION_Y, yDistance, 0f));
+        play(a, getAnimator(mFolder, SCALE_PROPERTY, initialScale, finalScale));
+        play(a, getAnimator(items, ITEMS_TEXT_COLOR_PROPERTY, Color.TRANSPARENT, finalTextColor));
+        play(a, getAnimator(mFolderBackground, "color", initialColor, finalColor));
+        play(a, new RoundedRectRevealOutlineProvider(initialSize / 2f, finalRadius, startRect,
                 endRect).createRevealAnimator(mFolder, !mIsOpening));
 
         a.addListener(new AnimatorListenerAdapter() {
@@ -272,18 +277,43 @@
 
             Animator translationX = getAnimator(btv, View.TRANSLATION_X, xDistance, 0f);
             translationX.setInterpolator(previewItemInterpolator);
-            animatorSet.play(translationX);
+            play(animatorSet, translationX);
 
             Animator translationY = getAnimator(btv, View.TRANSLATION_Y, yDistance, 0f);
             translationY.setInterpolator(previewItemInterpolator);
-            animatorSet.play(translationY);
+            play(animatorSet, translationY);
 
             Animator scaleAnimator = getAnimator(btv, SCALE_PROPERTY, initialScale, finalScale);
             scaleAnimator.setInterpolator(previewItemInterpolator);
-            animatorSet.play(scaleAnimator);
+            play(animatorSet, scaleAnimator);
+
+            if (mFolder.getItemCount() > FolderIcon.NUM_ITEMS_IN_PREVIEW) {
+                // These delays allows the preview items to move as part of the Folder's motion,
+                // and its only necessary for large folders because of differing interpolators.
+                if (mIsOpening) {
+                    translationX.setStartDelay(mDelay);
+                    translationY.setStartDelay(mDelay);
+                    scaleAnimator.setStartDelay(mDelay);
+                }
+                translationX.setDuration(translationX.getDuration() - mDelay);
+                translationY.setDuration(translationY.getDuration() - mDelay);
+                scaleAnimator.setDuration(scaleAnimator.getDuration() - mDelay);
+            }
 
             animatorSet.addListener(new AnimatorListenerAdapter() {
                 @Override
+                public void onAnimationStart(Animator animation) {
+                    super.onAnimationStart(animation);
+                    // Necessary to initialize values here because of the start delay.
+                    if (mIsOpening) {
+                        btv.setTranslationX(xDistance);
+                        btv.setTranslationY(yDistance);
+                        btv.setScaleX(initialScale);
+                        btv.setScaleY(initialScale);
+                    }
+                }
+
+                @Override
                 public void onAnimationEnd(Animator animation) {
                     super.onAnimationEnd(animation);
                     btv.setTranslationX(0.0f);
@@ -295,6 +325,11 @@
         }
     }
 
+    private void play(AnimatorSet as, Animator a) {
+        a.setDuration(mDuration);
+        as.play(a);
+    }
+
     private TimeInterpolator getPreviewItemInterpolator() {
         if (mFolder.getItemCount() > FolderIcon.NUM_ITEMS_IN_PREVIEW) {
             // With larger folders, we want the preview items to reach their final positions faster