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