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: - <?xml version= "1.0" encoding= "utf-8" ?>
-
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
- <svg version= "1.1" xmlns= "http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink" x= "0px" y= "0px"
- width= "512px" height= "512px" viewBox= "0 0 512 512" style= "enable-background:new 0 0 512 512;" xml:space= "preserve" >
- <path id= "cpu" d="
- 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
- 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
-
- M193 . 304 , 408.261V462h- 17.913 v- 53.739H193.304z
- M264 . 957 , 408.261V462h- 17.914v- 53.739H264.957z
- M300.783 , 408.261V462h - 17.914v - 53.739H300.783z
- M229 . 13 , 408.261 V462h- 17.913v- 53.739H229.13z
- M336 . 609 , 408.261V462h- 17.914v- 53.739H336.609z
-
- M193.304,50v53.739h - 17.913V50H193.304z
- M264 . 957 , 50 v53.739h- 17.914V50H264.957z
- M300.783,50v53.739h - 17.914V50H300.783z
- M229 . 13,50v53.739h- 17.913V50H229.13z
- M336.609,50v53.739h - 17.914V50H336.609z
-
- M408 . 261 , 318.695H462v17.914h- 53.739V318.695z
- M408 . 261 , 247.043H462v17.914h- 53.739V247.043z
- M408 . 261 , 211.217 H462v17.913h- 53.739V211.217z
- M408 . 261 , 282.869H462v17.914h- 53.739V282.869z
- M408 . 261 , 175.391H462v17.913h- 53.739V175.391z
-
- M50 , 318.695h53.739v17.914H50V318.695z
- M50 , 247.043h53.739v17.914H50V247.043z
- M50 , 211.217h53.739v17.913H50V211.217z
- M50, 282.869 h53.739v17.914H50V282.869z
- M50, 175 .391h53.739v17.913H50V175.391z" />
- </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. - <vector xmlns:android= "http://schemas.android.com/apk/res/android"
- android:height= "64dp"
- android:width= "64dp"
- android:viewportHeight= "600"
- android:viewportWidth= "600" >
-
- </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.
- <vector xmlns:android= "http://schemas.android.com/apk/res/android"
- android:height= "64dp"
- android:width= "64dp"
- android:viewportHeight= "600"
- android:viewportWidth= "600" >
-
- <path
- android:name= "cpu"
- android:fillColor= "#000000"
- android:pathData="
- 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
- 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"
- />
-
- <path
- android:name= "wires_bottom"
- android:fillColor= "#000000"
- android:pathData="
- M193 . 304 , 408.261V462h- 17.913 v- 53.739H193.304z
- M264 . 957 , 408.261V462h- 17.914v- 53.739H264.957z
- M300.783 , 408.261V462h - 17.914v - 53.739H300.783z
- M229 . 13 , 408.261 V462h- 17.913v- 53.739H229.13z
- M336. 609 , 408 .261V462h- 17 .914v- 53 .739H336.609z"
- />
-
- <path
- android:name= "wires_top"
- android:fillColor= "#000000"
- android:pathData="
- M193.304,50v53.739h - 17.913V50H193.304z
- M264 . 957 , 50 v53.739h- 17.914V50H264.957z
- M300.783,50v53.739h - 17.914V50H300.783z
- M229 . 13,50v53.739h- 17.913V50H229.13z
- M336. 609,50v53 . 739 h- 17.914V50H336.609z "
- />
-
- <path
- android:name= "wires_right"
- android:fillColor= "#000000"
- android:pathData="
- M408 . 261 , 318.695H462v17.914h- 53.739V318.695z
- M408 . 261 , 247.043H462v17.914h- 53.739V247.043z
- M408 . 261 , 211.217 H462v17.913h- 53.739V211.217z
- M408 . 261 , 282.869H462v17.914h- 53.739V282.869z
- M408 . 261 , 175.391H462v17.913h- 53.739V175.391z "
- />
-
- <path
- android:name= "wires_left"
- android:fillColor= "#000000"
- android:pathData="
- M50 , 318.695h53.739v17.914H50V318.695z
- M50 , 247.043h53.739v17.914H50V247.043z
- M50 , 211.217h53.739v17.913H50V211.217z
- M50, 282.869 h53.739v17.914H50V282.869z
- M50, 175 .391h53.739v17.913H50V175.391z"
- />
-
- </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: - <vector xmlns:android= "http://schemas.android.com/apk/res/android"
- android:height= "64dp"
- android:width= "64dp"
- android:viewportHeight= "600"
- android:viewportWidth= "600" >
-
- <group
- android:name= "cpu_box" >
- <path
- android:name= "cpu"
- android:fillColor= "#000000"
- android:pathData="
- 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
- 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 "/>
- </group>
- <group
- android:name= "bottom" >
- <path
- android:name= "wires_bottom"
- android:fillColor= "#000000"
- android:pathData="
- M193 . 304 , 408.261V462h- 17.913 v- 53.739H193.304z
- M264 . 957 , 408.261V462h- 17.914v- 53.739H264.957z
- M300.783 , 408.261V462h - 17.914v - 53.739H300.783z
- M229 . 13 , 408.261 V462h- 17.913v- 53.739H229.13z
- M336. 609 , 408 .261V462h- 17 .914v- 53 .739H336.609z" />
- </group>
- <group android:name= "top" >
- <path
- android:name= "wires_top"
- android:fillColor= "#000000"
- android:pathData="
- M193.304,50v53.739h - 17.913V50H193.304z
- M264 . 957 , 50 v53.739h- 17.914V50H264.957z
- M300.783,50v53.739h - 17.914V50H300.783z
- M229 . 13,50v53.739h- 17.913V50H229.13z
- M336. 609,50v53 . 739 h- 17.914V50H336.609z " />
- </group>
- <group android:name= "right" >
- <path
- android:name= "wires_right"
- android:fillColor= "#000000"
- android:pathData="
- M408 . 261 , 318.695H462v17.914h- 53.739V318.695z
- M408 . 261 , 247.043H462v17.914h- 53.739V247.043z
- M408 . 261 , 211.217 H462v17.913h- 53.739V211.217z
- M408 . 261 , 282.869H462v17.914h- 53.739V282.869z
- M408. 261 , 175.391H462v17.913h- 53.739V175.391z " />
- </group>
- <group android:name= "left" >
- <path
- android:name= "wires_left"
- android:fillColor= "#000000"
- android:pathData="
- M50 , 318.695h53.739v17.914H50V318.695z
- M50 , 247.043h53.739v17.914H50V247.043z
- M50 , 211.217h53.739v17.913H50V211.217z
- M50, 282.869 h53.739v17.914H50V282.869z
- M50, 175 .391h53.739v17.913H50V175.391z" />
- </group>
-
- </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. - <?xml version= "1.0" encoding= "utf-8" ?>
- <set xmlns:android= "http://schemas.android.com/apk/res/android" >
- <objectAnimator
- android:propertyName= "translateY"
- android:valueType= "floatType"
- android:valueFrom= "0"
- android:valueTo= "-10"
- android:repeatMode= "reverse"
- android:repeatCount= "infinite"
- android:duration= "250" />
- </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. - <?xml version= "1.0" encoding= "utf-8" ?>
- <animated-vector xmlns:android= "http://schemas.android.com/apk/res/android"
- android:drawable= "@drawable/vector_drawable_cpu" >
-
- <target
- android:animation= "@animator/pulse_top"
- android:name= "top" />
-
- <target
- android:animation= "@animator/pulse_right"
- android:name= "right" />
-
- <target
- android:animation= "@animator/pulse_left"
- android:name= "left" />
-
- <target
- android:animation= "@animator/pulse_bottom"
- android:name= "bottom" />
- </animated-vector>
Once all the necessary XML files have been prepared, you can add animated_cpu.xml to the ImageView for display. - <ImageView
- android:id= "@+id/cpu"
- android:layout_width= "64dp"
- android:layout_height= "64dp"
- android:src= "@drawable/animated_cpu" />
To start the animation, you need to get the Animatable instance from the ImageView and call start. - ImageView mCpuImageView = (ImageView) findViewById( R.id.cpu );
- Drawable drawable = mCpuImageView.getDrawable();
- if (drawable instanceof Animatable) {
- ((Animatable) drawable).start();
- }
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. - <string name= "left_arrow" >M300, 70 l 0 , 70 - 70 ,- 70 0 , 0 70 ,-70z</string>
-
- <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. - <vector xmlns:android= "http://schemas.android.com/apk/res/android"
- android:height= "64dp"
- android:width= "64dp"
- android:viewportHeight= "600"
- android:viewportWidth= "600" >
-
- <path
- android:name= "left_arrow"
- android:fillColor= "#000000"
- android:pathData= "@string/left_arrow" />
- /vector>
The main difference between the CPU animation and the graphical change examples mentioned here is in the animator_left_right_arrow.xml file. - <?xml version= "1.0" encoding= "utf-8" ?>
- <set xmlns:android= "http://schemas.android.com/apk/res/android" >
-
- <objectAnimator
- android:duration= "1000"
- android:propertyName= "pathData"
- android:valueFrom= "@string/left_arrow"
- android:valueTo= "@string/right_arrow"
- android:valueType= "pathType"
- android:repeatMode= "reverse"
- android:repeatCount= "-1" />
-
- </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. - <?xml version= "1.0" encoding= "utf-8" ?>
- <animated-vector xmlns:android= "http://schemas.android.com/apk/res/android"
- android:drawable= "@drawable/vector_drawable_left_arrow" >
-
- <target
- android:name= "left_arrow"
- android:animation= "@animator/animator_left_right_arrows" />
- </animated-vector>
***, you also need to assign the animation drawable to ImageView and then start running it in your Java code. - <ImageView
- android:id= "@+id/left_right_arrow"
- android:layout_width= "64dp"
- android:layout_height= "64dp"
- android:layout_below= "@+id/cpu"
- android:src= "@drawable/animated_arrow" />
- mArrowImageView = (ImageView) findViewById( R.id.left_right_arrow );
- drawable = mArrowImageView.getDrawable();
- if (drawable instanceof Animatable) {
- ((Animatable) drawable).start();
- }
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. |