1. Code
  2. Coding Fundamentals
  3. Tools

Using Android's VectorDrawable Class

Scroll to top

Introduction

While Android does not support SVGs (Scalable Vector Graphics) directly, Lollipop introduced a new class called VectorDrawable, which allows designers and developers to draw assets in a similar fashion using only code.

In this article, you will learn how to create a VectorDrawable with XML files and animate them in your projects. This is only supported for devices running Android 5.0 or above, and currently there are no support-library implementations. The source files of this tutorial can be found on GitHub.

1. Creating a Vector Drawable

The main similarity between a VectorDrawable and a standard SVG image is that both are drawn out using a path value. While understanding how SVG paths are drawn is out of the scope of this article, official documentation can be found on the W3C website. For this article, you'll simply need to know that the path tag is where the drawing occurs. Let's take a look at the SVG file that draws out the following image:

Image of a CPU that will be drawn out in codeImage of a CPU that will be drawn out in codeImage of a CPU that will be drawn out in code

There are five major parts to this image:

  • a square for the CPU body made up of two arches
  • four groups of five lines that represent the CPU's wires

The following code draws this image out as an SVG:

1
<?xml version="1.0" encoding="utf-8"?>
2
3
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
     width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
6
<path id="cpu" d="

7
	M341.087,157.478c7.417,0,13.435,6.018,13.435,13.435v170.174 c0,7.417-6.018,13.435-13.435,13.435H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913 c0-7.417,6.018-13.435,13.435-13.435H341.087z

8
	M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785 0,35.826-16.041,35.826-35.826V157.478z 

9


10
	M193.304,408.261V462h-17.913 v-53.739H193.304z 

11
	M264.957,408.261V462h-17.914v-53.739H264.957z 

12
	M300.783,408.261V462h-17.914v-53.739H300.783z 

13
	M229.13,408.261 V462h-17.913v-53.739H229.13z 

14
	M336.609,408.261V462h-17.914v-53.739H336.609z

15


16
	M193.304,50v53.739h-17.913V50H193.304z

17
	M264.957,50 v53.739h-17.914V50H264.957z

18
	M300.783,50v53.739h-17.914V50H300.783z

19
	M229.13,50v53.739h-17.913V50H229.13z

20
	M336.609,50v53.739 h-17.914V50H336.609z

21


22
	M408.261,318.695H462v17.914h-53.739V318.695z

23
	M408.261,247.043H462v17.914h-53.739V247.043z

24
	M408.261,211.217 H462v17.913h-53.739V211.217z

25
	M408.261,282.869H462v17.914h-53.739V282.869z

26
	M408.261,175.391H462v17.913h-53.739V175.391z

27


28
	M50,318.695h53.739v17.914H50V318.695z 

29
	M50,247.043h53.739v17.914H50V247.043z 

30
	M50,211.217h53.739v17.913H50V211.217z 

31
	M50,282.869 h53.739v17.914H50V282.869z 

32
	M50,175.391h53.739v17.913H50V175.391z" />
33
</svg>

While this may look a little overwhelming, you don't actually need to fully understand how everything is drawn out to implement a VectorDrawable in your code. However, it should be noted that I separated each of the five sections into their own unique block in the code for readability.

The top section consists of two arches to draw out the rounded square and the sections that follow represent the bottom, top, right, and left sets of lines respectively. To turn this SVG code into a VectorDrawable, you first need to define the vector object in XML. The following code is taken from the vector_drawable_cpu.xml file in the sample code for this article.

1
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2
    android:height="64dp"
3
    android:width="64dp"
4
    android:viewportHeight="600"
5
    android:viewportWidth="600" >
6
    
7
</vector>

Next, you can add in the path data. The following code is broken up into five different path tags rather than one large path.

1
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2
    android:height="64dp"
3
    android:width="64dp"
4
    android:viewportHeight="600"
5
    android:viewportWidth="600" >
6
7
        <path
8
            android:name="cpu"
9
            android:fillColor="#000000"
10
            android:pathData="

11
                M341.087,157.478 c7.417,0,13.435,6.018,13.435,13.435 v170.174c0,7.417-6.018,13.435-13.435,13.435 H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913c0-7.417,6.018-13.435,13.435-13.435H341.087z

12
                M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785,0,35.826-16.041,35.826-35.826V157.478z"
13
        />
14
15
        <path
16
            android:name="wires_bottom"
17
            android:fillColor="#000000"
18
            android:pathData="

19
                M193.304,408.261V462h-17.913 v-53.739H193.304z

20
                M264.957,408.261V462h-17.914v-53.739H264.957z

21
                M300.783,408.261V462h-17.914v-53.739H300.783z

22
                M229.13,408.261 V462h-17.913v-53.739H229.13z

23
                M336.609,408.261V462h-17.914v-53.739H336.609z"
24
        />
25
26
        <path
27
            android:name="wires_top"
28
            android:fillColor="#000000"
29
            android:pathData="

30
                M193.304,50v53.739h-17.913V50H193.304z

31
                M264.957,50 v53.739h-17.914V50H264.957z

32
                M300.783,50v53.739h-17.914V50H300.783z

33
                M229.13,50v53.739h-17.913V50H229.13z

34
                M336.609,50v53.739 h-17.914V50H336.609z" 
35
        />
36
37
        <path
38
            android:name="wires_right"
39
            android:fillColor="#000000"
40
            android:pathData="

41
                M408.261,318.695H462v17.914h-53.739V318.695z

42
                M408.261,247.043H462v17.914h-53.739V247.043z

43
                M408.261,211.217 H462v17.913h-53.739V211.217z

44
                M408.261,282.869H462v17.914h-53.739V282.869z

45
                M408.261,175.391H462v17.913h-53.739V175.391z" 
46
        />
47
        
48
        <path
49
            android:name="wires_left"
50
            android:fillColor="#000000"
51
            android:pathData="

52
                M50,318.695h53.739v17.914H50V318.695z

53
                M50,247.043h53.739v17.914H50V247.043z

54
                M50,211.217h53.739v17.913H50V211.217z

55
                M50,282.869 h53.739v17.914H50V282.869z

56
                M50,175.391h53.739v17.913H50V175.391z" 
57
        />
58
59
</vector>

As you can see, each path section simply uses the pathData attribute for drawing. You can now include the VectorDrawable XML file as a drawable in a standard ImageView and it will scale to any size your app requires, without needing to use any Java code.

2. Animating Vector Drawables

Now that you know how to create images using only code, it's time to have a little fun and animate them. In the following animation, you'll notice that each of the groups of wires are pulsing towards and away from the CPU.

Example of animated VectorDrawablesExample of animated VectorDrawablesExample of animated VectorDrawables

To achieve this effect, you will need to wrap each section that you want to animate in a <group> tag. The updated version of vector_drawable_cpu.xml then looks like this:

1
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2
    android:height="64dp"
3
    android:width="64dp"
4
    android:viewportHeight="600"
5
    android:viewportWidth="600" >
6
7
    <group
8
        android:name="cpu_box">
9
        <path
10
            android:name="cpu"
11
            android:fillColor="#000000"
12
            android:pathData="

13
            M341.087,157.478 c7.417,0,13.435,6.018,13.435,13.435 v170.174c0,7.417-6.018,13.435-13.435,13.435 H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913c0-7.417,6.018-13.435,13.435-13.435H341.087z

14
            M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785,0,35.826-16.041,35.826-35.826V157.478z "/>
15
    </group>
16
    <group
17
        android:name="bottom">
18
        <path
19
            android:name="wires_bottom"
20
            android:fillColor="#000000"
21
            android:pathData="

22
        M193.304,408.261V462h-17.913 v-53.739H193.304z

23
        M264.957,408.261V462h-17.914v-53.739H264.957z

24
        M300.783,408.261V462h-17.914v-53.739H300.783z

25
        M229.13,408.261 V462h-17.913v-53.739H229.13z

26
        M336.609,408.261V462h-17.914v-53.739H336.609z" />
27
    </group>
28
    <group android:name="top">
29
        <path
30
            android:name="wires_top"
31
            android:fillColor="#000000"
32
            android:pathData="

33
        M193.304,50v53.739h-17.913V50H193.304z

34
        M264.957,50 v53.739h-17.914V50H264.957z

35
        M300.783,50v53.739h-17.914V50H300.783z

36
        M229.13,50v53.739h-17.913V50H229.13z

37
        M336.609,50v53.739 h-17.914V50H336.609z " />
38
    </group>
39
    <group android:name="right">
40
        <path
41
            android:name="wires_right"
42
            android:fillColor="#000000"
43
            android:pathData="

44
        M408.261,318.695H462v17.914h-53.739V318.695z

45
        M408.261,247.043H462v17.914h-53.739V247.043z

46
        M408.261,211.217 H462v17.913h-53.739V211.217z

47
        M408.261,282.869H462v17.914h-53.739V282.869z

48
        M408.261,175.391H462v17.913h-53.739V175.391z" />
49
    </group>
50
    <group android:name="left">
51
        <path
52
            android:name="wires_left"
53
            android:fillColor="#000000"
54
            android:pathData="

55
        M50,318.695h53.739v17.914H50V318.695z

56
        M50,247.043h53.739v17.914H50V247.043z

57
        M50,211.217h53.739v17.913H50V211.217z

58
        M50,282.869 h53.739v17.914H50V282.869z

59
        M50,175.391h53.739v17.913H50V175.391z" />
60
    </group>
61
62
</vector>

Next, you will want to create animators for each animation type. In this case, there is one for each group of wires for a total of four. Below is an example of the top group's animation and you will also need one for the bottom, left, and right. Each of the animator XML files can be found in the sample code.

1
<?xml version="1.0" encoding="utf-8"?>
2
<set xmlns:android="http://schemas.android.com/apk/res/android">
3
    <objectAnimator
4
        android:propertyName="translateY"
5
        android:valueType="floatType"
6
        android:valueFrom="0"
7
        android:valueTo="-10"
8
        android:repeatMode="reverse"
9
        android:repeatCount="infinite"
10
        android:duration="250" />
11
</set>

As you can see, the propertyName is set to translateY, which means the animation will move along the Y axis. The valueFrom and valueTo control the begin and end location. By setting repeatMode to reverse and repeatCount to infinite, the animation will loop forever as long as the VectorDrawable is visible. The duration of the animation is set to 250, which is the time in milliseconds.

To apply the animations to your drawable file, you will need to create a new animated-vector XML file to associate the animators with the VectorDrawable groups. The following code is used to create the animated_cpu.xml file.

1
<?xml version="1.0" encoding="utf-8"?>
2
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:drawable="@drawable/vector_drawable_cpu">
4
5
    <target
6
        android:animation="@animator/pulse_top"
7
        android:name="top" />
8
9
    <target
10
        android:animation="@animator/pulse_right"
11
        android:name="right" />
12
13
    <target
14
        android:animation="@animator/pulse_left"
15
        android:name="left" />
16
17
    <target
18
        android:animation="@animator/pulse_bottom"
19
        android:name="bottom" />
20
</animated-vector>

When all of your XML are ready to go, you can use the animated_cpu.xml drawable in an ImageView to display it.

1
<ImageView
2
    android:id="@+id/cpu"
3
    android:layout_width="64dp"
4
    android:layout_height="64dp"
5
    android:src="@drawable/animated_cpu" />

To start your animation, you will need to get an instance of the Animatable from the ImageView and call start.

1
ImageView mCpuImageView = (ImageView) findViewById( R.id.cpu );
2
Drawable drawable = mCpuImageView.getDrawable();
3
if (drawable instanceof Animatable) {
4
    ((Animatable) drawable).start();
5
}

After start has been called, the wires on the CPU image will start to move with very minimal Java code used.

3. Transforming Vector Drawables

A common use case for a VectorDrawable is transforming one image into another, such as the action bar icon that changes from a hamburger icon into an arrow. To do this, both the source and destination paths must follow an identical format for the number of elements. For this example we will define the left and right facing arrows seen above as strings.

1
<string name="left_arrow">M300,70 l 0,70 -70,-70 0,0 70,-70z</string>
2
<string name="right_arrow">M300,70 l 0,-70 70,70 0,0 -70,70z</string>

Next, you will need to create an initial drawable for an arrow using the path for left_arrow. In the sample code, it is called vector_drawable_left_arrow.xml.

1
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2
    android:height="64dp"
3
    android:width="64dp"
4
    android:viewportHeight="600"
5
    android:viewportWidth="600" >
6
7
    <path
8
        android:name="left_arrow"
9
        android:fillColor="#000000"
10
        android:pathData="@string/left_arrow"/>
11
</vector>

The main difference between the CPU animation and the transformation lies in the animator_left_right_arrow.xml file.

1
<?xml version="1.0" encoding="utf-8"?>
2
<set xmlns:android="http://schemas.android.com/apk/res/android">
3
4
    <objectAnimator
5
        android:duration="1000"
6
        android:propertyName="pathData"
7
        android:valueFrom="@string/left_arrow"
8
        android:valueTo="@string/right_arrow"
9
        android:valueType="pathType"
10
        android:repeatMode="reverse"
11
        android:repeatCount="-1"/>
12
13
</set>

You'll notice the valueFrom and valueTo properties reference the path data for the left and right arrow, the valueType is set to pathType and propertyName is set to pathData. When these are set, the animator will know to change one set of path data to the other. When the animator is finished, you need to associate the VectorDrawable with the objectAnimator using a new animated-vector object.

1
<?xml version="1.0" encoding="utf-8"?>
2
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:drawable="@drawable/vector_drawable_left_arrow">
4
5
    <target
6
        android:name="left_arrow"
7
        android:animation="@animator/animator_left_right_arrows" />
8
</animated-vector>

Finally, you'll simply need to associate the animated drawable with an ImageView and start the animation in your Java code.

1
<ImageView
2
    android:id="@+id/left_right_arrow"
3
    android:layout_width="64dp"
4
    android:layout_height="64dp"
5
    android:layout_below="@+id/cpu"
6
    android:src="@drawable/animated_arrow" />
1
mArrowImageView = (ImageView) findViewById( R.id.left_right_arrow );
2
drawable = mArrowImageView.getDrawable();
3
if (drawable instanceof Animatable) {
4
    ((Animatable) drawable).start();
5
}

Conclusion

As you have seen, the VectorDrawable class is fairly straightforward to use and allows for a lot of customization to add simple animations. While the VectorDrawable class is currently only available for devices running Android 5.0 and above, they will be invaluable as more devices support Lollipop and future Android releases.

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.