VectorDrawable pathData commands in Android

Open any VectorDrawable XML file and you are greeted with some cryptic commands in the pathData attribute.

<vector xmlns:android=""
	android:viewportWidth="600" >
		android:rotation="45.0" >
			android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />

Those who works with Paths on a regular basis may be able to interpret this command and tell you what shape it makes. For the rest of us, it can be a bit of a mystery.

What is a VectorDrawable

A VectorDrawable is an XML representation of a Vector. Unlike popular image formats like Bitmap, JPEG, GIF and PNG, Vectors do not lose quality as they are scaled up or down. This makes bundling of images with different densities unnecessary, hence saving you a lot of APK bloat. In effect, VectorDrawables contains path commands on (how to draw lines and arcs) and just like Path commands when working with Canvas, drawing and rendering VectorDrawables is time and memory consuming process which is why VectorDrawable’s are best used for simple flat graphics.

Understanding pathData commands

Let me just start by saying that no matter how much you study path commands, unless you’re a genius, there will be a limit to what you can understand. Vector graphic programs don’t exactly have clean and human readable code as a high priority. After vector graphics files like SVGs are piped through Android Studios VectorDrawable generator, they become a lot cleaner and easier to read, however, I’ve found that a lot of the commands can still be a lot more complex that what you may need. Then to understand circles and arcs just requires you to have a lot of imagination or some serious mathematics prowess.

The basics

Basic path commands are comprised of alphabet followed by one or more numbers. The numbers are often comma separated but don’t have to be. E.g.

M100,100 L300,100 L200,300 z
M 100 100 L 300 100 L 200 300 z

The alphabet can be upper or lowercase. Uppercase means absolute position, lowercase means relative position.


M or m (X,Y)+
moveto: Move cursor to position, uppercase is absolute, lowercase is relative
moveto commands are followed by X,Y coordinates. There can be more than one set of coordinates following an M command, these are treated as implicit lineto commands.

Z or z

closepath: Draws a line from the current position of the cursor to the start position of the path. Does not have any parameters.

L or l (X,Y)+

lineto: Draws a line from the current position to the position specified by X,Y. Uppercase means absolute coordinates, lowercase means relative coordinates. You can have more than one set of coordinates following a lineto command. If you want specify more than one set of coordinates, it means that you’re creating a polyline (shape consisting of multiple string lines).

H or h (X)+

Horizontal lineto draws a horizontal line from the current cursor position to the position specified by X. If there are multiple X coordinates following the command, this is treated as a polyline. The Y coordinate remains unchanged. Uppercase H is absolute coordinates, lowercase h is relative coordinates.

V or v (Y)+

Vertical lineto draws a vertical line from the current cursor position to the position specified by Y. If there are multiple Y coordinates following the command, this is treated as a polyline. The X coordinate remains unchanged. Uppercase V is absolute coordinates, lowercase v is relative coordinates.


With this much in mind, lets interpret the command we had above:

M100,100 L300,100 L200,300 z

M100,100: Move cursor to absolute coordinates X=100 Y=100px.
L300,100: Draw a line to X=300 Y=100 (starting position was 100,100).
L200,300: Draw a line to X=200 Y=300 (starting position was 300,100).
z: Close path, straight line from current position to 100,100. When you close the path is when the shape is filled with the fill colour specified. You can leave this out if you shape doesn’t need to close, like in a check mark or a cross.

If we sketch it out, you’ll notice that the shape is an upside down triangle!

If we put this inside a simple VectorDrawable XML we can see the result:

<vector xmlns:android=""
    <!-- intrinsic size of the drawable -->
    <!-- size of the virtual canvas -->
        android:pathData="M100,100 L300,100 L200,300 z"/>