有没有办法在AnimatedVectorDrawables中监听动画结束

时间:2015-03-02 14:47:50

标签: android animation listener android-vectordrawable

我创建了AnimatedVectorDrawable,它运行得很好,现在我正在寻找一种方法来更改动画或在视图完成后隐藏视图。我希望有一个听众,但它看起来不像。有人可以帮忙吗?

修改

所以我找到了一种解决方法,但不是一种非常优雅的方式。我做的是创建一个线程并轮询动画是否正在运行。

new Runnable() {
    public void run() {
        while(mLoop) {
            if(mAnimatedVectorDrawable.isRunning()) {
                Thread.sleep(mPollingInterval);
            } else {
                mLoop = false;
                // TODO what ever
            }
        }
    }
};

如果有人找到更好的解决方案,请分享。

4 个答案:

答案 0 :(得分:16)

尚未尝试过,但Android 6.0在Animatable2界面中有一个registerAnimationCallback方法

编辑:是的,这适用于Android 6.0模拟器:

mAnimatedVectorDrawable.registerAnimationCallback (new Animatable2.AnimationCallback(){
    public void onAnimationEnd(Drawable drawable){
        //Do something
    }
}

Edit2:看起来他们没有在支持lib 23.2+的AnimatedVectorDrawableCompat中添加对此的支持:(

Edit3:看起来在支持lib 25.3.0

中添加了它

谢谢卡森!

答案 1 :(得分:7)

我的第一直觉是获取源代码,添加一些回调,并从中创建自定义drawable。当然,这意味着没有xml支持。

事实证明AnimatedVectorDrawable使用VectorDrawable's个私有方法。所以,这种方法不起作用。

我们可以围绕AnimatedVectorDrawable创建一个简单的包装类并添加回调:

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();
    }
}

您的代码如下:

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();

但是,这正是您使用setStartDelay所做的。所以我不知道这会有多大用处。

编辑:所有这些也可以在扩展的AnimatedVectorDrawable中实现。但是,你将完全失去xml支持。

答案 2 :(得分:4)

很奇怪,没有直接的API来获得这个。我想一个不涉及覆盖的解决方法只是在你的动画集中找到花费最多时间的动画,然后发布延迟的runnable来隐藏视图。

int longestAnimationTime = 500; //miliseconds, defined in XML possibly?
drawable.start();
drawableView.postDelayed(new Runnable() {

        @Override
        public void run() {
            drawableView.setVisibility(View.GONE);
        }
}, longestAnimationTime);

缺点是它涉及对最长动画时间进行硬编码,但只要您在动画XML和代码中引用相同的常量值,它就能正常工作,不需要覆盖。

答案 3 :(得分:0)

我发现了同样的问题。我正在尝试为正在绘制的圆圈和内部的勾选设置动画。

我能做的最好的就是玩持续时间。像这样:

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();

有一个听众

会很棒