Changing LauncherViewPropertyAnimator to use ValueAnimator
Using ValueAnimator allows better support for changes in Animator
APIs.
Bug: 35218222
Change-Id: I4efa470b4bb686328539d35d8e23e297a4ac885a
diff --git a/src/com/android/launcher3/LauncherViewPropertyAnimator.java b/src/com/android/launcher3/LauncherViewPropertyAnimator.java
index 4406a2c..9bafc2a 100644
--- a/src/com/android/launcher3/LauncherViewPropertyAnimator.java
+++ b/src/com/android/launcher3/LauncherViewPropertyAnimator.java
@@ -17,259 +17,90 @@
package com.android.launcher3;
import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.TimeInterpolator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
import android.view.View;
-import android.view.ViewPropertyAnimator;
+
+import com.android.launcher3.anim.AnimationLayerSet;
import java.util.ArrayList;
-import java.util.EnumSet;
-public class LauncherViewPropertyAnimator extends Animator implements AnimatorListener {
+/**
+ * Extension of {@link ValueAnimator} to provide an interface similar to
+ * {@link android.view.ViewPropertyAnimator}.
+ */
+public class LauncherViewPropertyAnimator extends ValueAnimator {
- enum Properties {
- TRANSLATION_X,
- TRANSLATION_Y,
- SCALE_X,
- SCALE_Y,
- ROTATION_Y,
- ALPHA,
- START_DELAY,
- DURATION,
- INTERPOLATOR,
- WITH_LAYER
- }
- EnumSet<Properties> mPropertiesToSet = EnumSet.noneOf(Properties.class);
- ViewPropertyAnimator mViewPropertyAnimator;
- View mTarget;
+ private final View mTarget;
+ private final ArrayList<PropertyValuesHolder> mProperties;
- float mTranslationX;
- float mTranslationY;
- float mScaleX;
- float mScaleY;
- float mRotationY;
- float mAlpha;
- long mStartDelay;
- long mDuration;
- TimeInterpolator mInterpolator;
- ArrayList<Animator.AnimatorListener> mListeners = new ArrayList<>();
- boolean mRunning = false;
- FirstFrameAnimatorHelper mFirstFrameHelper;
+ private boolean mPrepared = false;
- public LauncherViewPropertyAnimator(View target) {
- mTarget = target;
- }
-
- @Override
- public void addListener(Animator.AnimatorListener listener) {
- mListeners.add(listener);
- }
-
- @Override
- public void cancel() {
- if (mViewPropertyAnimator != null) {
- mViewPropertyAnimator.cancel();
- }
- }
-
- @Override
- public Animator clone() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void end() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public long getDuration() {
- return mDuration;
- }
-
- @Override
- public ArrayList<Animator.AnimatorListener> getListeners() {
- return mListeners;
- }
-
- @Override
- public long getStartDelay() {
- return mStartDelay;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationCancel(this);
- }
- mRunning = false;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationEnd(this);
- }
- mRunning = false;
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationRepeat(this);
- }
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- // This is the first time we get a handle to the internal ValueAnimator
- // used by the ViewPropertyAnimator.
- mFirstFrameHelper.onAnimationStart(animation);
-
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationStart(this);
- }
- mRunning = true;
- }
-
- @Override
- public boolean isRunning() {
- return mRunning;
- }
-
- @Override
- public boolean isStarted() {
- return mViewPropertyAnimator != null;
- }
-
- @Override
- public void removeAllListeners() {
- mListeners.clear();
- }
-
- @Override
- public void removeListener(Animator.AnimatorListener listener) {
- mListeners.remove(listener);
- }
-
- @Override
- public Animator setDuration(long duration) {
- mPropertiesToSet.add(Properties.DURATION);
- mDuration = duration;
- return this;
- }
-
- @Override
- public void setInterpolator(TimeInterpolator value) {
- mPropertiesToSet.add(Properties.INTERPOLATOR);
- mInterpolator = value;
- }
-
- @Override
- public void setStartDelay(long startDelay) {
- mPropertiesToSet.add(Properties.START_DELAY);
- mStartDelay = startDelay;
- }
-
- @Override
- public void setTarget(Object target) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void setupEndValues() {
-
- }
-
- @Override
- public void setupStartValues() {
+ public LauncherViewPropertyAnimator(View view) {
+ mTarget = view;
+ mProperties = new ArrayList<>();
+ setTarget(mTarget);
+ addListener(new TransientStateUpdater(mTarget));
}
@Override
public void start() {
- mViewPropertyAnimator = mTarget.animate();
-
- // FirstFrameAnimatorHelper hooks itself up to the updates on the animator,
- // and then adjusts the play time to keep the first two frames jank-free
- mFirstFrameHelper = new FirstFrameAnimatorHelper(mViewPropertyAnimator, mTarget);
-
- if (mPropertiesToSet.contains(Properties.TRANSLATION_X)) {
- mViewPropertyAnimator.translationX(mTranslationX);
+ if (!mPrepared) {
+ mPrepared = true;
+ setValues(mProperties.toArray(new PropertyValuesHolder[mProperties.size()]));
}
- if (mPropertiesToSet.contains(Properties.TRANSLATION_Y)) {
- mViewPropertyAnimator.translationY(mTranslationY);
- }
- if (mPropertiesToSet.contains(Properties.SCALE_X)) {
- mViewPropertyAnimator.scaleX(mScaleX);
- }
- if (mPropertiesToSet.contains(Properties.ROTATION_Y)) {
- mViewPropertyAnimator.rotationY(mRotationY);
- }
- if (mPropertiesToSet.contains(Properties.SCALE_Y)) {
- mViewPropertyAnimator.scaleY(mScaleY);
- }
- if (mPropertiesToSet.contains(Properties.ALPHA)) {
- mViewPropertyAnimator.alpha(mAlpha);
- }
- if (mPropertiesToSet.contains(Properties.START_DELAY)) {
- mViewPropertyAnimator.setStartDelay(mStartDelay);
- }
- if (mPropertiesToSet.contains(Properties.DURATION)) {
- mViewPropertyAnimator.setDuration(mDuration);
- }
- if (mPropertiesToSet.contains(Properties.INTERPOLATOR)) {
- mViewPropertyAnimator.setInterpolator(mInterpolator);
- }
- if (mPropertiesToSet.contains(Properties.WITH_LAYER)) {
- mViewPropertyAnimator.withLayer();
- }
- mViewPropertyAnimator.setListener(this);
- mViewPropertyAnimator.start();
LauncherAnimUtils.cancelOnDestroyActivity(this);
+ super.start();
}
public LauncherViewPropertyAnimator translationX(float value) {
- mPropertiesToSet.add(Properties.TRANSLATION_X);
- mTranslationX = value;
+ mProperties.add(PropertyValuesHolder.ofFloat(View.TRANSLATION_X, value));
return this;
}
public LauncherViewPropertyAnimator translationY(float value) {
- mPropertiesToSet.add(Properties.TRANSLATION_Y);
- mTranslationY = value;
+ mProperties.add(PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, value));
return this;
}
public LauncherViewPropertyAnimator scaleX(float value) {
- mPropertiesToSet.add(Properties.SCALE_X);
- mScaleX = value;
+ mProperties.add(PropertyValuesHolder.ofFloat(View.SCALE_X, value));
return this;
}
public LauncherViewPropertyAnimator scaleY(float value) {
- mPropertiesToSet.add(Properties.SCALE_Y);
- mScaleY = value;
- return this;
- }
-
- public LauncherViewPropertyAnimator rotationY(float value) {
- mPropertiesToSet.add(Properties.ROTATION_Y);
- mRotationY = value;
+ mProperties.add(PropertyValuesHolder.ofFloat(View.SCALE_Y, value));
return this;
}
public LauncherViewPropertyAnimator alpha(float value) {
- mPropertiesToSet.add(Properties.ALPHA);
- mAlpha = value;
+ mProperties.add(PropertyValuesHolder.ofFloat(View.ALPHA, value));
return this;
}
public LauncherViewPropertyAnimator withLayer() {
- mPropertiesToSet.add(Properties.WITH_LAYER);
+ AnimationLayerSet listener = new AnimationLayerSet();
+ listener.addView(mTarget);
+ addListener(listener);
return this;
}
+
+ private static class TransientStateUpdater extends AnimatorListenerAdapter {
+ private final View mView;
+
+ TransientStateUpdater(View v) {
+ mView = v;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mView.setHasTransientState(true);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mView.setHasTransientState(false);
+ }
+ }
}
diff --git a/src/com/android/launcher3/anim/AnimationLayerSet.java b/src/com/android/launcher3/anim/AnimationLayerSet.java
index 42706ff..d2f5e78 100644
--- a/src/com/android/launcher3/anim/AnimationLayerSet.java
+++ b/src/com/android/launcher3/anim/AnimationLayerSet.java
@@ -20,23 +20,29 @@
import android.animation.AnimatorListenerAdapter;
import android.view.View;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
/**
* Helper class to automatically build view hardware layers for the duration of an animation.
*/
public class AnimationLayerSet extends AnimatorListenerAdapter {
- private final HashSet<View> mViews = new HashSet<>();
+ private final HashMap<View, Integer> mViewsToLayerTypeMap = new HashMap<>();
public void addView(View v) {
- mViews.add(v);
+ mViewsToLayerTypeMap.put(v, v.getLayerType());
}
@Override
public void onAnimationStart(Animator animation) {
// Enable all necessary layers
- for (View v : mViews) {
+ Iterator<Map.Entry<View, Integer>> itr = mViewsToLayerTypeMap.entrySet().iterator();
+ while (itr.hasNext()) {
+ Map.Entry<View, Integer> entry = itr.next();
+ View v = entry.getKey();
+ entry.setValue(v.getLayerType());
v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (v.isAttachedToWindow() && v.getVisibility() == View.VISIBLE) {
v.buildLayer();
@@ -46,8 +52,10 @@
@Override
public void onAnimationEnd(Animator animation) {
- for (View v : mViews) {
- v.setLayerType(View.LAYER_TYPE_NONE, null);
+ Iterator<Map.Entry<View, Integer>> itr = mViewsToLayerTypeMap.entrySet().iterator();
+ while (itr.hasNext()) {
+ Map.Entry<View, Integer> entry = itr.next();
+ entry.getKey().setLayerType(entry.getValue(), null);
}
}
}