有没有一种方法可以监听AnimatedVectorDrawables动画结束的事件?

22

我已经创建了一个AnimatedVectorDrawable,它工作得很好,现在我正在寻找一种方法来改变动画或在其完成后隐藏视图。我希望有一个监听器,但看起来并没有。有人可以帮忙吗?

编辑

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

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

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


我认为你需要fork它,以便访问Animator实例并能够为其注册监听器。 - CommonsWare
谢谢,但我希望有更简单的东西。 - Naveen Dissanayake
1
我为此提交了一个功能请求:https://code.google.com/p/android/issues/detail?id=158780 - CommonsWare
1
一个类似的功能请求是在Java中直接管理动画和vectorDrawable:https://code.google.com/p/android/issues/detail?id=98322 - fstephany
请查看此答案:https://dev59.com/ol8d5IYBdhLWcg3wsT0b#35738726 - Amit Vaghela
4个回答

22

我还没有尝试过,但是Android 6.0中有一个从Animatable2接口继承而来的registerAnimationCallback方法可以用于此操作。

编辑:是的,在Android 6.0模拟器中可以使用此方法。

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

编辑2: 看起来他们还没有在支持库23.2+的AnimatedVectorDrawableCompat中添加对此的支持 :(

编辑3: 看起来这在支持库25.3.0中得到了添加

谢谢Carson!


2
现在,这可以与最新的支持库配合使用,支持到API 14。 - Carson Holzheimer
这是非常干净的解决方案,并且向后兼容Android支持。 - mochadwi

8

我的第一反应是获取源代码,添加一些回调函数,并将其创建为自定义可绘制对象。当然,这意味着无法支持xml。

实际上,AnimatedVectorDrawable 使用了 VectorDrawable 的私有方法。因此,这种方法行不通。

我们可以创建一个简单的包装类来包裹 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支持。


4

奇怪的是没有直接获取它的API。我想一个不涉及重写的解决方法就是在你的动画集中找到持续时间最长的动画,然后发布延迟可运行以隐藏视图。

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

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

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


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

拥有一个监听器会很棒


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接