Home » Android » android – Error while trying to test AnimatedVectorDrawable, "Can't morph from x to z"

android – Error while trying to test AnimatedVectorDrawable, "Can't morph from x to z"

Posted by: admin June 15, 2020 Leave a comment

Questions:

I wanted to make an AnimatedVectorDrawable, so that my FAB can look atleast somewhat as fabulous as this one, with animations and stuff.

I found this great tutorial, on how to use & implement them etc, and later on I found a very usefull tool for converting SVG’s into Android-VectorDrawables, and converted these two images:
https://github.com/google/material-design-icons/blob/master/content/svg/design/ic_add_48px.svg
https://github.com/google/material-design-icons/blob/master/action/svg/design/ic_done_48px.svg

Now this is the xml-“code” that I’ve come up with:

drawable/vector_add.xml:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="48"
    android:viewportHeight="48">

    <group>
        <path
            android:pathData="M0 0h48v48h-48Z" />
        <path
            android:name="add"
            android:fillColor="#ffffff"
            android:pathData="M38 26h-12v12h-4v-12h-12v-4h12v-12h4v12h12v7Z" />
    </group>
</vector>

anim/add_to_done.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M38 26h-12v12h-4v-12h-12v-4h12v-12h4v12h12v7Z"
        android:valueTo="M18 32.34l-8.34-8.34-2.83 2.83 11.17 11.17 24-24-2.83-2.83Z"
        android:valueType="pathType" />
</set>

drawable/ic_add.xml:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_add">

    <target
        android:name="add"
        android:animation="@anim/anim_plus_to_done" />

</animated-vector>

If I run this code, I just end up with this error:

Caused by: android.view.InflateException: Binary XML file line #3 Can't morph from M38 26h-12v12h-4v-12h-12v-4h12v-12h4v12h12v4Z to M18 32.34l-8.34-8.34-2.83 2.83 11.17 11.17 24-24-2.83-2.83Z
        at android.animation.AnimatorInflater.setupAnimatorForPath(AnimatorInflater.java:337)
        at android.animation.AnimatorInflater.parseAnimatorFromTypeArray(AnimatorInflater.java:283)
        at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:618)
        at android.animation.AnimatorInflater.loadObjectAnimator(AnimatorInflater.java:577)
        at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:529)
        at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:542

My guess would be that the two path’s in the two svg’s are too different, so Android cannot handle the animation on it’s own, and I need to make like several VectorDrawables for each animation “checkpoint”.

…I’m probably completly way off with that theory, but it’s the most logical I can come up with..

I do not have much experience (nor any experince at all for that matter) working with Vectors & Illustrator etc, so any help you guys can come up with will be extremely appreciated.

Have a nice day,
and Merry Christmas.

Sincerely,
Måns.

How to&Answers:

The VectorDrawables you wish to morph must be compatible, meaning they must have simlar complexities; similar length and number of commands (this was mentioned by pksink).

This way I ended up solving this is taking the “plus” symbol and modifying is the dimensions manually in android studio until I had something that resembled a checkmark.

Plus Vector:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:viewportHeight="24"
    android:viewportWidth="24"
    android:width="24dp"
    android:height="24dp">

    <group android:name="plus_group" android:pivotX="12" android:pivotY="12">
        <path
            android:name="plus_path"
            android:strokeColor="@android:color/white"
            android:strokeWidth="3"
            android:pathData="M12,0L12,24M0,12,L24,12" />
    </group>
</vector>

CheckMark Vector:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:width="24dp"
    android:height="24dp">
    <group android:name="check_group"
        android:pivotX="12"
        android:translateX="0"
        android:pivotY="12">

        <path
            android:name="check_path"
            android:strokeColor="@android:color/white"
            android:strokeWidth="3"
            android:pathData="M20,0L06,20M0,14,L08,19" />
    </group>
</vector>

Notice that these have the same number of commands. The checkmark does not look perfect, but you cannot notice if you put it in a floating action button.

Additional tip: Move the pathData to a string variable. That way, it’s easier to maintain consistency in your objectAnimators.

Answer:

If you want to morph between arbitrary SVG images (or VectorDrawable) you need to align the corresponding paths in order to make them compatible for morphing.
This is a very tedious task, but there’s a command line tool that can do that for you: VectAling

You just need to run the VectAlign tool from the command line passing your original paths and it will automatically create “morphable” sequences.

Example of usage:

java -jar  vectalign.jar --start "M 10,20..." --end "M 30,30..."

Output:

--------------------
  ALIGNMENT RESULT  
-------------------- 
# new START sequence:  
M 48.0,54.0 L 31.0,42.0 L 15.0,54.0 L 21.0,35.0 L 6.0,23.0 L 25.0,23.0 L 25.0,23.0 L 25.0,23.0 L 25.0,23.0 L 32.0,4.0 L 40.0,23.0 L 58.0,23.0 L 42.0,35.0 L 48.0,54.0 

# new END sequence:  
M 48.0,54.0 L 48.0,54.0 L 48.0,54.0 L 48.0,54.0 L 31.0,54.0 L 15.0,54.0 L 10.0,35.0 L 6.0,23.0 L 25.0,10.0 L 32.0,4.0 L 40.0,10.0 L 58.0,23.0 L 54.0,35.0 L 48.0,54.0 

Now you can use these new sequences in your Android project and morph between them as usual using an AnimatedVectorDrawable!

You can also pass SVG files:

java -jar  vectalign.jar --start image1.svg --end image2.svg

This is one of the samples from the VectAlign demo:

enter image description here