重新启动AnimatedVectorDrawableCompat的AnimatorSet

5
这是我需要用 AnimatedVectorDrawableCompat 实现的效果。 vector_drawable_anim.xml
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
                 android:drawable="@drawable/vector_drawable">
    <target
        android:name="star"
        android:animation="@animator/star_anim"/>
</animated-vector>

vector_drawable.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="500px"
        android:height="500px"
        android:viewportHeight="500"
        android:viewportWidth="500">
    <group
        android:name="star_group"
        android:scaleX="5.0"
        android:scaleY="5.0">
        <path
            android:name="star"
            android:pathData="M 50.0,90.0 L 82.9193546357,27.2774101308 L 12.5993502926,35.8158045183 Z"
            android:strokeColor="@color/colorAccent"
            android:strokeWidth="1"/>
    </group>
</vector>

star_anim.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:ordering="sequentially">

    <objectAnimator
        android:duration="1000"
        android:propertyName="trimPathStart"
        android:valueFrom="1"
        android:valueTo="0"/>

    <objectAnimator
        android:duration="1000"
        android:propertyName="trimPathEnd"
        android:valueFrom="1"
        android:valueTo="0"/>

</set>

但是AnimatorSet不能设置repeatMode

如果我设置objectAnimatorrepeatMode,第二个objectAnimator将不会显示。

我该怎么办?


https://dev59.com/Ml4c5IYBdhLWcg3wuMN7 - AskNilesh
<objectAnimator android:propertyName="pathData" android:repeatCount="-1" - Ultimo_m
3个回答

3

把它放在一个线程内循环,直到ImageView被销毁怎么样?

完美运行的代码示例:

  ImageView animatedImageView = (ImageView) findViewById(R.id.iv);
  AnimatedVectorDrawableCompat animatedVectorDrawable = (AnimatedVectorDrawableCompat) animatedImageView.getDrawable();

        new Thread(new Runnable() {
            public void run() {
                while (animatedImageView != null) {
                    try {
                        animatedImageView.post(new Runnable() {
                            @Override
                            public void run() {
                                animatedVectorDrawable.start();
                            }
                        });
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

另外,您可以使用registerAnimationCallback(),由azizbekian提到,然后跟随这个git gist代码示例

import android.app.Activity;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ImageView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView iv = (ImageView) findViewById(R.id.pin);
        final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) iv.getDrawable();
        avd.registerAnimationCallback(new Animatable2.AnimationCallback() {
            @Override
            public void onAnimationEnd(Drawable drawable) {
                avd.start();
            }
        });
        avd.start();
    }
}

如果我使用post来延迟avd.start(),它可以工作。我认为当在onAnimationEnd()时动画仍在运行时,这可能是一个bug! - cs x
是的!我亲自测试过,结果很好。@csx - Prokash Sarkar
如果我使用你的第一种方法,我会得到以下错误信息 - Caused by: java.lang.ClassCastException: android.graphics.drawable.AnimatedVectorDrawable cannot be cast to androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat。第二种方法适用于23及以上版本。 - Aman Verma
@AmanVerma AnimatedVectorDrawable来自android.graphics,而AnimatedVectorDrawable来自androidx.vectordrawable。您混淆了一个android小部件和一个androidx小部件。请检查您的导入和布局。 - Prokash Sarkar

2
几乎符合您想要的,且使用纯XML格式:

几乎符合您想要的,且使用纯XML格式:

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">

    <objectAnimator
        android:duration="1000"
        android:propertyName="trimPathStart"
        android:repeatCount="infinite"
        android:startOffset="1000"
        android:valueFrom="1"
        android:valueTo="0" />

    <objectAnimator
        android:duration="1000"
        android:propertyName="trimPathStart"
        android:repeatCount="infinite"
        android:startOffset="1000"
        android:repeatMode="reverse"
        android:valueFrom="0"
        android:valueTo="1" />

</set>

你想要的与实际不同之处在于路径修剪的方向。但它看起来很棒。

1
您可以在动画上设置监听器,并在其完成start()后再次启动它:

    AnimatedVectorDrawableCompat avdc = ...;
    avdc.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
        @Override
        public void onAnimationEnd(Drawable drawable) {
            avdc.start();
        }
    });

请注意,registerAnimationCallback() 从支持库版本25.3.0开始可用。

我找不到Animatable2Compat,如何加载Animatable2Compat? - cs x
它从支持库版本 25.3.0 开始可用。 - azizbekian
但是在21以下的版本中,AnimatedVectorDrawableCompat使用ObjectAnimator,而AnimatorSet不会重复。 - cs x
无法理解您的意思。您能重新表述一下吗?更新支持库版本如何与“低于21”的功能产生冲突? - azizbekian
我的意思是在android-19上无法重复动画。 - cs x

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