How to use Android's VectorDrawable class to draw vector images

How to use Android's VectorDrawable class to draw vector images

Drawing vector graphics is not difficult - how to use Android's VectorDrawable class

Contents

Although the Android system does not directly support SVG (Scalable Vector Graphics), the Lollipop version introduces a new class called VectorDrawable, which allows designers and developers to generate similar drawing effects in pure code.

In today's article, we will learn how to create a VectorDrawable using XML files and display it in your own project in an animated way. This feature can only be implemented on devices running Android 5.0 or higher, and there is currently no support library implementation. The relevant source files in this tutorial can be obtained through the GitHub website.

1. Create a Vector Drawable

From a similar perspective, both VectorDrawable and standard SVG graphics are drawn using path values. However, how to use SVG path to draw graphics is beyond the scope of this article. You can click here to get the necessary instructions from the W3C website. In this article, we only need to understand that the role of the path tag is to draw graphics. Let's start with the SVG file and see how the following graphics are drawn:

This graphic consists of five main parts:

The CPU body is a rounded quadrilateral consisting of two arched arcs.

Four groups of five lines each, used as extension circuits for the CPU.

The following code shows how to draw the above graphics in 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.739h - 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>

Although it looks a bit complicated, you don't need to dwell on the specific meaning of the above code, and it will not affect the VectorDrawable drawing work we will do next. However, it should be emphasized that I treat the five major graphic components mentioned above as independent blocks in the code to enhance the readability of the code content.

First, we need to use two arcs to draw a rounded quadrilateral. In the following content, we will discuss how to express the extension lines of the four directions: up, down, left, and right. In order to convert the above SVG code into VectorDrawable, you first need to define the vector object in XML. The following code is extracted from the vector_drawable_cpu.xml file in the sample code of 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>
After that, you can add path data to it. The following code is also split into five different path tags instead of treating it as a whole, which is of course also to ensure the readability of the content.
  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 segment is simply drawn using the pathData property. We can now include the VectorDrawable XML file as a drawable in a standard ImageView that can be scaled to any size required by our application - without changing any Java code.

2. Add animation effects to Vector Drawables

Now that we know how to create graphics in pure code, let's have some fun and animate them. In the following animation, you can see that the groups of lines that are extensions are moving towards and away from the CPU itself.

To achieve this, you need to wrap each clip containing the animation effect in a <group> tag. The modified version of vector_drawable_cpu.xml will look 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, we need to create animator files for each animation type. In this example, each group of lines uses an animator, which means a total of four animators are needed. The following code shows the animation effect of the top line. You will also need to set similar effects for the bottom, left, and right lines. Each animator XML file is included in the sample code of this project.

  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, propertyName is set to translateY, which means the animation will move along the Y axis. valueFrom and valueTo control the start and end points of the translation. By setting repeatMode to reverse and repeatCount to infinite, the entire animation will loop forever, and the effect will be reflected in the VectorDrawable. The duration of the animation is set to 250, which is the duration in milliseconds.

To apply this animation to your own drawable file, you need to create a new animated-vector XML file to assign these animators to each VectorDrawable group. 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>

Once all the necessary XML files have been prepared, you can add animated_cpu.xml to the ImageView for display.

  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 the animation, you need to get the Animatable instance 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 is called, the line graphics in the CPU graphic will begin to move - the whole process only needs a small amount of Java code to achieve.

3. How Vector Drawables change

One of the most common uses of VectorDrawable is to convert one graphic to another, such as changing the icon in the action bar from a hamburger to an arrow. To do this, both the source and target paths must have the same format to ensure the same number of elements. In this example, we will try to convert the left arrow to the right arrow as shown in the previous picture.

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

Next, you need to create an initial drawable for left_arrow using path. In the sample code, we name it 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 graphical change examples mentioned here is 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 may have noticed that the valueFrom and valueTo properties reference the path data for the left and right arrows, and that the valueType is set to pathType and the propertyName is set to pathData. Once this is done, the animator will know how to convert one set of path data to another. When the animator is finished, we also need to assign the VectorDrawable to the objectAnimator using the 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>

***, you also need to assign the animation drawable to ImageView and then start running it 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" />
  7. mArrowImageView = (ImageView) findViewById( R.id.left_right_arrow );
  8. drawable = mArrowImageView.getDrawable();
  9. if (drawable instanceof Animatable) {
  10. ((Animatable) drawable).start();
  11. }

Summary <br /> As you can see, the VectorDrawable class is very easy to use and allows developers to implement a lot of simple animation effects in a customized way. Although the VectorDrawable class is currently only available for devices running Android 5.0 and higher, it will play a more important role as more devices begin to support Lollipop and subsequent Android versions.

<<:  The details that make or break things: The little-known highlights from Google I/O 2015

>>:  Summary of Web App Development Skills

Recommend

Is the smart bracelet just a transitional product?

Estimated global shipments of wearable electronic...

What new product operators must know about operational planning!

As a programmer who switched to a product manager...

Stop it! If you love picking your nose, be careful not to damage your brain!

Source: Dr. Curious The cover image of this artic...

Postpartum weight loss: Easily train your waist and back

Postpartum weight loss: Easily train your waist a...

8 ways to play red envelopes to activate the community

Community operation is the term that operators ar...

Tips for placing video ads in the wedding photography industry!

Introduction: As the weather gets warmer, the wed...

Analyze the user life cycle and improve app engagement

When your app has acquired a certain number of us...

Li Yu uses words to tell you how exciting life with ups and downs is!

This article was first published by Hunzhi Educat...

The “last mile” of integrated marketing

When we talk about ROI, it is no longer an abbrev...

Asus ZenFone 6 review: large screen, Intel chip, 1,000 yuan

The screen size of ASUS ZenFone 6 is 6.0 inches, w...