Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to restart android AnimatedVectorDrawables animations?

I have a kinda complex vector drawable that I want to animate. I used @RomanNurik's web tool to create the animation from a svg

That gives me a valid <animated-vector> according to the documentatios. It's an "all in one" XML file.

The xml has the drawable divided in 2 groups, each group containing 2 paths and has also added 4 animations, just as follows:

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
    <aapt:attr name="android:drawable">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="56dp"
            android:height="56dp"
            android:viewportHeight="56.0"
            android:viewportWidth="56.0">
            <group
                android:name="group_1"
                android:pivotX="25"
                android:pivotY="25">
                <path
                    android:name="path_3_1"
                    ... />
                <path
                    android:name="path"
                    ... />
            </group>
            <group
                android:name="group"
                android:pivotX="25"
                android:pivotY="25">
                <path
                    android:name="path_1"
                    ... />
                <path
                    android:name="path_2"
                    ... />
            </group>
        </vector>
    </aapt:attr>
    <target android:name="path">
        <aapt:attr name="android:animation">
            <set xmlns:android="http://schemas.android.com/apk/res/android">
                <objectAnimator
                    android:name="path"
                    ... />
                <objectAnimator
                    android:name="path"
                  .../>
            </set>
        </aapt:attr>
    </target>
    <target android:name="group_1">
        <aapt:attr name="android:animation">
            <set xmlns:android="http://schemas.android.com/apk/res/android">
                <objectAnimator
                    android:name="group_1"
                    ... />
                <objectAnimator
                    android:name="group_1"
                    ... />
                <objectAnimator
                    android:name="group_1"
                    ... />
                <objectAnimator
                    android:name="group_1"
                    ... />
            </set>
        </aapt:attr>
    </target>
    <target android:name="group">
        <aapt:attr name="android:animation">
            <set xmlns:android="http://schemas.android.com/apk/res/android">
                <objectAnimator
                    android:name="group"
                    ... />
                <objectAnimator
                    android:name="group"
                    ... />
                <objectAnimator
                    android:name="group"
                    ... />
                <objectAnimator
                    android:name="group"
                    ... />
            </set>
        </aapt:attr>
    </target>
    <target android:name="path_3_1">
        <aapt:attr name="android:animation">
            <set xmlns:android="http://schemas.android.com/apk/res/android">
                <objectAnimator
                    android:name="path_3_1"
                    ... />
                <objectAnimator
                    android:name="path_3_1"
                    ... />
            </set>
        </aapt:attr>
    </target>
</animated-vector>

Issue number 1:

I cannot use android:repeatCount="infinite" since the ObjectAnimators have different android:duration and android:startOffset values, that would mess up the animation after some runs. So the way to go is repeat it programmatically. Fair enough.

Issue number 2:

Neither AnimatedVectorDrawableCompat or AnimatedVectorDrawable have a method that says animation should loop.

Issue number 3:

AnimatedVectorDrawableCompat does not have a registerAnimationCallback() so I can listen to onAnimationEnd and restart the animation myself. At this point, I gave up on retrocompatibility.

Issue number 4:

The current implementation I have that uses registerAnimationCallback() from AnimatedVectorDrawable only works at android API 25, even though the methods were added in API 23

AnimatedVectorDrawable drawable = (AnimatedVectorDrawable) context().getDrawable(R.drawable.long_press_anim);
imageView.setImageDrawable(drawable);
drawable.registerAnimationCallback(new Animatable2.AnimationCallback() {
    @Override
    public void onAnimationEnd(Drawable drawable) {
        super.onAnimationEnd(drawable);
        ((AnimatedVectorDrawable) drawable).start();
    }
});
drawable.start();

In API 23 and 24 the animation runs as a one-shot, it does not repeat.

Any ideas how to solve this? I;m about to give up and use a shit png sequence instead.

like image 544
Felipe Conde Avatar asked Jan 20 '17 15:01

Felipe Conde


People also ask

How do I use animated icons on Android?

Use AnimatedVectorDrawable You normally define animated vector drawables in three XML files: A vector drawable with the <vector> element in res/drawable/ An animated vector drawable with the <animated-vector> element in res/drawable/ One or more object animators with the <objectAnimator> element in res/animator/


1 Answers

I have the same issue so I did this:

// setup and set animation
AnimatedVectorDrawableCompat animatedVector = AnimatedVectorDrawableCompat.create(context, R.drawable.listening_vector_anim);
imageView.setImageDrawable(animatedVector);

// loop animation!
new Thread(() -> {
    while (imageView.isAttachedToWindow()) {
        try {
            imageView.post(() -> animatedVector.start());
            Thread.sleep(2000); //depends on your animation duration
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}).start();

This thread will die when the ImageView detach from window.

like image 181
Mohsen Mirhoseini Avatar answered Sep 30 '22 01:09

Mohsen Mirhoseini