Created
April 23, 2014 12:10
-
-
Save AAverin/11212822 to your computer and use it in GitHub Desktop.
A simple animation manager capable of playing several parallel Animation objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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