Search code examples
androidandroid-animationandroid-drawableandroid-vectordrawable

Using AnimatedVectorDrawables to make the Android robo wave


I'm trying to create a simple animation of the Android robot logo waving. I have my VectorDrawable and AnimatedVectorDrawable defined as below:

VectorDrawable (drawable/android.xml)

<vector android:height="240dp" android:viewportHeight="345.0"
    android:viewportWidth="294.0" android:width="240dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#a4c639"
        android:pathData="M206.62,4.72L206.62,4.72A6.5,6.5 57.81,0 1,209.16 13.56L173.77,77.4A6.5,6.5 76.8,0 1,164.93 79.94L164.93,79.94A6.5,6.5 76.8,0 1,162.4 71.1L197.79,7.26A6.5,6.5 57.81,0 1,206.62 4.72z"
        android:strokeColor="#FFF" android:strokeWidth="1"/>
    <path android:fillColor="#a4c639"
        android:pathData="M74.07,7.53L74.07,7.53A6.5,6.5 112,0 1,82.9 10.06L118.29,73.91A6.5,6.5 124.14,0 1,115.76 82.74L115.76,82.74A6.5,6.5 124.14,0 1,106.92 80.21L71.53,16.36A6.5,6.5 112,0 1,74.07 7.53z"
        android:strokeColor="#FFF" android:strokeWidth="1"/>

    <path
        android:name="leftArm"
        android:fillColor="#ff0000"
        android:pathData="M28,111L28,111A24,24 0,0 1,52 135L52,220A24,24 0,0 1,28 244L28,244A24,24 0,0 1,4 220L4,135A24,24 0,0 1,28 111z"
        />

    <path android:fillColor="#a4c639" android:pathData="M56,111a91,84 0,1 0,182 0a91,84 0,1 0,-182 0z"/>
    <path android:fillColor="#a4c639" android:pathData="M78,90L216,90A22,22 0,0 1,238 112L238,250A22,22 0,0 1,216 272L78,272A22,22 0,0 1,56 250L56,112A22,22 0,0 1,78 90z"/>
    <path
        android:name="rightArm"
        android:fillColor="#00f"
        android:pathData="M264,111L264,111A24,24 0,0 1,288 135L288,220A24,24 0,0 1,264 244L264,244A24,24 0,0 1,240 220L240,135A24,24 0,0 1,264 111z"/>
    <path android:fillColor="#FFF" android:pathData="m52,114.5h190"
        android:strokeColor="#FFF" android:strokeWidth="1"/>
    <path android:fillColor="#FFF"
        android:pathData="M105,70m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
        android:strokeColor="#FFF" android:strokeWidth="1"/>
    <path android:fillColor="#FFF"
        android:pathData="M189,70m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
        android:strokeColor="#FFF" android:strokeWidth="1"/>
</vector>

AnimatedVectorDrawable (drawable/wave.xml)

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

    <target
        android:animation="@animator/waveanim"
        android:name="leftArm"/>


</animated-vector>

and heres animator/waveanim.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="4000"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:propertyName="pivotX"
        android:valueFrom="0.0"
        android:valueTo="50.0"
        />

</set>

I did previously try a few different things, such as wrapping the "leftArm" path in a <group> and trying to animated random properties. I was able to get some random movements but nothing like what I was going for, so I scrapped that code and went back to the beginning.

Btw, heres a screenie of what it looks like currently:

http://prntscr.com/bk5e53

So how can I make the arm wave at me?


Solution

  • Well if you wave at the Android maybe it will just wave back...

    However, in case that doesn't work, here's how to approach it.

    First, it's always useful to have the official documentation handy for reference. From here we can see that android:rotation is a property of the <group> tag, so you were going down the correct path when you wrapped the left arm in a <group> tag, you will need to do that.

    The other properties to be aware of are pivotX and pivotY. Again I can see that pivotX appears in your question, but not where it should be! The pivot point of a group determines what part of the graphic is the centre of the rotation. So if you consider for example, a square. If the pivot point is in the centre, imagine sticking a pin in the middle and spinning the square around it. If the pivot point was the top left, imagine sticking a pin right in that corner and making the whole square swing around the pinned corner.

    In your case you probably want to work out the coordinates for the middle of the shoulder and set that as your pivot. Your pivot point stays where it is; the rotation changes.

    So that part of your VectorDrawable would look something like this:

    ...
    <group
      android:name="leftArmGroup"
      android:pivotX=     //the x and y coordinates of the shoulder
      android:pivotY=     //
      android:rotation="0">
        <path
        android:name="leftArm"
        android:fillColor="#ff0000"
        android:pathData="M28,111L28,111A24,24 0,0 1,52 135L52,220A24,24 0,0 1,28 244L28,244A24,24 0,0 1,4 220L4,135A24,24 0,0 1,28 111z"
        />
    </group>
    ...
    

    Your animated vector will now need to target leftArmGroup instead of leftArm and your objectAnimator will be animating android:propertyName="rotation" property(in degrees, eg. 0 to 360 would be a full rotation). The 'rotation=0' part that I've included in the snippet above doesn't technically need to be there(zero is default), but it's handy to have so you can quickly try different numbers and see how it looks in the preview window.

    Let me know if you want further detail on anything.