I have created an AnimatedVectorDrawable, it works pretty well, now I am looking for a way to change the animation or hide the view after it finishes. I was hoping there was
Not tried this yet but Android 6.0 has a registerAnimationCallback method from the Animatable2 interface for this
Edit: yep this works in Android 6.0 emulator:
mAnimatedVectorDrawable.registerAnimationCallback (new Animatable2.AnimationCallback(){
public void onAnimationEnd(Drawable drawable){
//Do something
}
}
Edit2: looks like they haven't added support for this in the AnimatedVectorDrawableCompat from support lib 23.2+ :(
Edit3: it looks like this got added in support lib 25.3.0
Thanks Carson!
I found the same problem. I am trying to animate a circle being drawn and a tick inside.
The best I could do is play with durations. Something like this:
final Drawable drawable = circle.getDrawable();
final Animatable animatable = (Animatable) drawable;
animatable.start();
tick.setAlpha(0f);
tick.animate().alpha(1f).setStartDelay(2000).setDuration(1).start();
final Drawable drawable2 = tick.getDrawable();
final Animatable animatable2 = (Animatable) drawable2;
animatable2.start();
It would be great to have a listener
It is strange that there is no direct API for getting this. I suppose a workaround that doesn't involve overrides would just be simply to find the animation in your set of animations that takes the most amount of time, then post a delayed runnable to hide the view.
int longestAnimationTime = 500; //miliseconds, defined in XML possibly?
drawable.start();
drawableView.postDelayed(new Runnable() {
@Override
public void run() {
drawableView.setVisibility(View.GONE);
}
}, longestAnimationTime);
Downside is that it involves hard coding your longest animation time, but as long as you are referencing the same constant value both in the animation XML and in code, it would work correctly, no overrides needed.
My first instinct was to take the source code, add some callbacks, and create a custom drawable out of it. Of course, that would have meant no xml support.
It turns out that AnimatedVectorDrawable
uses VectorDrawable's
private method(s). So, this approach won't work.
We could create a simple wrapper class around AnimatedVectorDrawable
and add callbacks:
public class AVDWrapper {
private Handler mHandler;
private Animatable mDrawable;
private Callback mCallback;
private Runnable mAnimationDoneRunnable = new Runnable() {
@Override
public void run() {
if (mCallback != null)
mCallback.onAnimationDone();
}
};
public interface Callback {
public void onAnimationDone();
public void onAnimationStopped();
}
public AVDWrapper(Animatable drawable,
Handler handler, Callback callback) {
mDrawable = drawable;
mHandler = handler;
mCallback = callback;
}
// Duration of the animation
public void start(long duration) {
mDrawable.start();
mHandler.postDelayed(mAnimationDoneRunnable, duration);
}
public void stop() {
mDrawable.stop();
mHandler.removeCallbacks(mAnimationDoneRunnable);
if (mCallback != null)
mCallback.onAnimationStopped();
}
}
Your code would look like:
final Drawable drawable = circle.getDrawable();
final Animatable animatable = (Animatable) drawable;
AVDWrapper.Callback callback = new AVDWrapper.Callback() {
@Override
public void onAnimationDone() {
tick.setAlpha(1f);
}
@Override
public void onAnimationStopped() {
// Okay
}
};
AVDWrapper avdw = new AVDWrapper(animatable, mHandler, callback);
//animatable.start();
avdw.start(2000L);
tick.setAlpha(0f);
//tick.animate().alpha(1f).setStartDelay(2000).setDuration(1).start();
// One wrapper is sufficient if the duration is same
final Drawable drawable2 = tick.getDrawable();
final Animatable animatable2 = (Animatable) drawable2;
animatable2.start();
But, this is exactly what you are doing with setStartDelay
. So I don't know how useful this will be.
Edit: All this can also be implemented inside an extended AnimatedVectorDrawable. But, you'll lose xml support altogether.