Merge "Add add/remove for AnimationListener's"
diff --git a/api/current.txt b/api/current.txt
index cd33830..cec80c7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -51901,6 +51901,7 @@
public abstract class Animation implements java.lang.Cloneable {
ctor public Animation();
ctor public Animation(android.content.Context, android.util.AttributeSet);
+ method public void addAnimationListener(android.view.animation.Animation.AnimationListener);
method protected void applyTransformation(float, android.view.animation.Transformation);
method public void cancel();
method protected android.view.animation.Animation clone() throws java.lang.CloneNotSupportedException;
@@ -51925,6 +51926,7 @@
method public void initialize(int, int, int, int);
method public boolean isFillEnabled();
method public boolean isInitialized();
+ method public void removeAnimationListener(android.view.animation.Animation.AnimationListener);
method public void reset();
method protected float resolveSize(int, float, int, int);
method public void restrictDuration(long);
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 0e1f767..95a346f 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -30,6 +30,9 @@
import dalvik.system.CloseGuard;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Abstraction for an Animation that can be applied to Views, Surfaces, or
* other objects. See the {@link android.view.animation animation package
@@ -182,10 +185,14 @@
Interpolator mInterpolator;
/**
- * The animation listener to be notified when the animation starts, ends or repeats.
+ * An animation listener to be notified when the animation starts, ends or repeats.
*/
- @UnsupportedAppUsage
- AnimationListener mListener;
+ private AnimationListener mListener;
+
+ /**
+ * A list of animation listeners to be notified when the animation starts, ends or repeats.
+ */
+ private List<AnimationListener> mListeners;
/**
* Desired Z order mode during animation.
@@ -371,23 +378,17 @@
if (mListenerHandler == null) {
mOnStart = new Runnable() {
public void run() {
- if (mListener != null) {
- mListener.onAnimationStart(Animation.this);
- }
+ dispatchAnimationStart();
}
};
mOnRepeat = new Runnable() {
public void run() {
- if (mListener != null) {
- mListener.onAnimationRepeat(Animation.this);
- }
+ dispatchAnimationRepeat();
}
};
mOnEnd = new Runnable() {
public void run() {
- if (mListener != null) {
- mListener.onAnimationEnd(Animation.this);
- }
+ dispatchAnimationEnd();
}
};
}
@@ -830,6 +831,10 @@
return true;
}
+ private boolean hasAnimationListener() {
+ return mListener != null || (mListeners != null && !mListeners.isEmpty());
+ }
+
/**
* <p>Binds an animation listener to this animation. The animation listener
* is notified of animation events such as the end of the animation or the
@@ -842,6 +847,32 @@
}
/**
+ * <p>Adds an animation listener to this animation. The animation listener
+ * is notified of animation events such as the end of the animation or the
+ * repetition of the animation.</p>
+ *
+ * @param listener the animation listener to be notified
+ */
+ public void addAnimationListener(AnimationListener listener) {
+ if (mListeners == null) {
+ mListeners = new ArrayList<>(1);
+ }
+ mListeners.add(listener);
+ }
+
+ /**
+ * <p>Removes an animation listener that has been added with
+ * {@link #addAnimationListener(AnimationListener)}.</p>
+ *
+ * @param listener the animation listener to be removed
+ */
+ public void removeAnimationListener(AnimationListener listener) {
+ if (mListeners != null) {
+ mListeners.remove(listener);
+ }
+ }
+
+ /**
* Gurantees that this animation has an interpolator. Will use
* a AccelerateDecelerateInterpolator is nothing else was specified.
*/
@@ -947,26 +978,59 @@
}
private void fireAnimationStart() {
- if (mListener != null) {
- if (mListenerHandler == null) mListener.onAnimationStart(this);
+ if (hasAnimationListener()) {
+ if (mListenerHandler == null) dispatchAnimationStart();
else mListenerHandler.postAtFrontOfQueue(mOnStart);
}
}
private void fireAnimationRepeat() {
- if (mListener != null) {
- if (mListenerHandler == null) mListener.onAnimationRepeat(this);
+ if (hasAnimationListener()) {
+ if (mListenerHandler == null) dispatchAnimationRepeat();
else mListenerHandler.postAtFrontOfQueue(mOnRepeat);
}
}
private void fireAnimationEnd() {
- if (mListener != null) {
- if (mListenerHandler == null) mListener.onAnimationEnd(this);
+ if (hasAnimationListener()) {
+ if (mListenerHandler == null) dispatchAnimationEnd();
else mListenerHandler.postAtFrontOfQueue(mOnEnd);
}
}
+ void dispatchAnimationStart() {
+ if (mListener != null) {
+ mListener.onAnimationStart(this);
+ }
+ if (mListeners != null && !mListeners.isEmpty()) {
+ for (AnimationListener listener : mListeners) {
+ listener.onAnimationStart(this);
+ }
+ }
+ }
+
+ void dispatchAnimationRepeat() {
+ if (mListener != null) {
+ mListener.onAnimationRepeat(this);
+ }
+ if (mListeners != null && !mListeners.isEmpty()) {
+ for (AnimationListener listener : mListeners) {
+ listener.onAnimationRepeat(this);
+ }
+ }
+ }
+
+ void dispatchAnimationEnd() {
+ if (mListener != null) {
+ mListener.onAnimationEnd(this);
+ }
+ if (mListeners != null && !mListeners.isEmpty()) {
+ for (AnimationListener listener : mListeners) {
+ listener.onAnimationEnd(this);
+ }
+ }
+ }
+
/**
* Gets the transformation to apply at a specified point in time. Implementations of this
* method should always replace the specified Transformation or document they are doing
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
index 767024e..03c6ca6 100644
--- a/core/java/android/view/animation/AnimationSet.java
+++ b/core/java/android/view/animation/AnimationSet.java
@@ -389,16 +389,12 @@
}
if (started && !mStarted) {
- if (mListener != null) {
- mListener.onAnimationStart(this);
- }
+ dispatchAnimationStart();
mStarted = true;
}
if (ended != mEnded) {
- if (mListener != null) {
- mListener.onAnimationEnd(this);
- }
+ dispatchAnimationEnd();
mEnded = ended;
}