【问题标题】:Is there a way to listen for animation end in AnimatedVectorDrawables有没有办法在 AnimatedVectorDrawables 中监听动画结束
【发布时间】:2015-05-02 23:18:08
【问题描述】:

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

编辑

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

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

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

【问题讨论】:

标签: android animation listener android-vectordrawable


【解决方案1】:

尚未尝试过,但 Android 6.0 有一个来自 Animatable2 接口的 registerAnimationCallback 方法

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

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

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

Edit3:看起来这是在支持库 25.3.0 中添加的

谢谢卡森!

【讨论】:

【解决方案2】:

奇怪的是没有直接的 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 和代码中引用相同的常量值,它就可以正常工作,无需覆盖。

【讨论】:

    【解决方案3】:

    我的第一反应是获取源代码,添加一些回调,并从中创建一个自定义的可绘制对象。当然,这意味着没有 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 的支持。

    【讨论】:

      【解决方案4】:

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

      我能做的最好的就是玩时长。像这样的:

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

      有一个听众会很棒

      【讨论】:

        猜你喜欢
        • 2012-02-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-06
        • 2021-02-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多