Skip to content

Instantly share code, notes, and snippets.

@AAverin
Created April 23, 2014 12:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AAverin/11212822 to your computer and use it in GitHub Desktop.
Save AAverin/11212822 to your computer and use it in GitHub Desktop.
A simple animation manager capable of playing several parallel Animation objects
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.animation.Animation;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
/**
* Created by AAverin on 13.02.14.
*/
public class AnimationManager {
private AnimationThread animationThread;
private Handler animationHandler;
private Handler uiHandler;
public boolean isStarted = false;
public boolean isPrepared = false;
public interface AnimationManagerListener {
public void onAnimationQueueFinished();
}
private ArrayList<AnimationManagerListener> listeners = new ArrayList<AnimationManagerListener>();
public synchronized void subscribe(AnimationManagerListener l) {
if (!listeners.contains(l)) {
listeners.add(l);
}
}
public synchronized void unsubscribe(AnimationManagerListener l) {
if (listeners.contains(l)) {
listeners.remove(l);
}
}
public synchronized void clearListeners() {
listeners.clear();
}
private synchronized void notifyOnAnimationQueueFinished() {
for (AnimationManagerListener l : listeners) {
l.onAnimationQueueFinished();
}
}
private static AnimationManager instance = null;
private AnimationManager() {
prepare();
}
public static AnimationManager getInstance() {
if (instance == null) {
instance = new AnimationManager();
}
return instance;
}
public void setUIHandler(Handler uiHandler) {
this.uiHandler = uiHandler;
}
private class AnimationThread extends Thread {
public void stopLooper() {
animationHandler.getLooper().quit();
}
private void sleep(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
Looper.prepare();
synchronized(this) {
if (animationHandler != null) {
animationHandler = null;
}
animationHandler = new Handler();
notifyAll();
}
Looper.loop();
}
/* waits for Looper initialization */
public boolean waitForHandler() {
synchronized(this) {
while(animationHandler == null) {
try {
Log.d("AnimationManager", "waiting for handler");
wait();
} catch (InterruptedException ignored) {}
}
}
return true;
}
}
public static class ParallelAnimations extends ArrayList<ViewWithAnimation> {
}
private ArrayList<ParallelAnimations> animationQueue = new ArrayList<ParallelAnimations>();
public int add(ParallelAnimations parallelAnimations) {
animationQueue.add(parallelAnimations);
return animationQueue.size() - 1;
}
public int add(ViewWithAnimation animation) {
ParallelAnimations singleAnimation = new ParallelAnimations();
singleAnimation.add(animation);
return add(singleAnimation);
}
public ParallelAnimations get(int index) {
return animationQueue.get(index);
}
private void prepare() {
animationQueue = new ArrayList<ParallelAnimations>();
animationThread = new AnimationThread();
animationThread.start();
animationThread.waitForHandler();
isPrepared = true;
}
public void executeAnimations() {
if (this.uiHandler == null) {
Log.e("AnimationManager", "No animation context set, please call setUIHandler(Activity)");
return;
}
isStarted = true;
animationHandler.post(new Runnable() {
@Override
public void run() {
Iterator<ParallelAnimations> iterator = animationQueue.iterator();
while(iterator.hasNext() && isStarted) {
final ParallelAnimations parallelAnimations = iterator.next();
synchronized (parallelAnimations) {
final CountDownLatch latch = new CountDownLatch(parallelAnimations.size());
for (final ViewWithAnimation viewWithAnimation : parallelAnimations) {
if (!isStarted) { //in case of stop called suddenly
while (latch.getCount() > 0) {
latch.countDown();
}
return;
}
uiHandler.post(new Runnable() {
@Override
public void run() {
if (viewWithAnimation.listener != null) {
viewWithAnimation.listener.beforeAnimation(viewWithAnimation);
}
if (viewWithAnimation.animation == null) {
return;
}
viewWithAnimation.animation.reset();
viewWithAnimation.animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
viewWithAnimation.animationStarted = true;
}
@Override
public void onAnimationEnd(Animation animation) {
viewWithAnimation.animationStarted = false;
if (viewWithAnimation.listener != null) {
viewWithAnimation.listener.afterAnimation(viewWithAnimation);
}
latch.countDown();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
viewWithAnimation.view.startAnimation(viewWithAnimation.animation);
}
});
}
if (isStarted) {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
notifyOnAnimationQueueFinished();
stop();
}
});
}
public void stop() {
isStarted = false;
clearListeners();
animationQueue.clear();
}
public void destroy() {
uiHandler = null;
animationThread.stopLooper();
animationHandler = null;
animationThread = null;
instance = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment