While developing Android Applications, supporting multiple resolutions are sometime nightmare to developers. Including multiple images for different resolutions also increases the project size. The solution is to use Vector Graphics such as SVG images. While Android does not support SVGs (Scalable Vector Graphics) directly, with the launch of Lollipop a new class was introduced called VectorDrawable, which allows designers and developers to draw assets in a similar fashion using only code.

Simply explained, vector graphics are a way of describing graphical elements using geometric shapes. They are particularly well suited to graphical elements created in packages such as Adobe Illustrator or Inkscape where simple geometric shapes may be combined in to much more complex elements.

1. What is VectorDrawable?

As the name implies, vector drawables are based on vector graphics, as opposed to raster graphics, vector graphics are a way of describing graphical elements using geometric shapes. It is similar to a SVG file. In Android Vector Drawable are created as XML files. Now there is no need to create different size image for mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi etc. We need only one vector file for multiple screen size devices. Also for older versions of Android that don’t support vector drawables, Vector Asset Studio can turn your vector drawables into different bitmap sizes for each screen density at runtime.

Here is the detailed information Vector Asset Studio.

Note: For this project I’m using gradle version 2.2, my suggession is to use 2.0+. However if you’re using gradle version below 2.0 then you’ll need to add some more code to the app level build.gradle file which I’ve mentioned below.

2. Creating Android Project

1. Create a new project in Android Studio from File ⇒ New Project and fill the project details.

2. Open build.gradle in app module, add the below line inside defaultConfig block.

vectorDrawables.useSupportLibrary = true

So the complete build.gradle looks like

apply plugin: 'com.android.application'

android {
   compileSdkVersion 25
   buildToolsVersion "25.0.2"
   defaultConfig {
       applicationId "info.androidhive.vectordrawable"
       minSdkVersion 17
       targetSdkVersion 25
       versionCode 1
       versionName "1.0"
       testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
       vectorDrawables.useSupportLibrary = true
   }
   buildTypes {
       release {
           minifyEnabled false
           proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
       }
   }
}

dependencies {
   compile fileTree(dir: 'libs', include: ['*.jar'])
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
       exclude group: 'com.android.support', module: 'support-annotations'
   })
   compile 'com.android.support:appcompat-v7:25.1.0'
   testCompile 'junit:junit:4.12'
}

If you are using gradle version below 2.0 then use following

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "info.androidhive.vectordrawable"
        minSdkVersion 17
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
        generatedDensities=[]
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    aaptOptions {
        additionalParameters "--no-version-vectors"
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
}

2.1 Creating VectorDrawable from Material Icons.

So let us start by creating VectorDrawables from Material Icons (Material Icons are the official icon set from Google that are designed under the material design guidelines, these icons are open source and are beautifully crafted, delightful, and easy to use in your web, Android, and iOS projects).

3. In the project Right click on the drawable directory

4. Go to New ⇒ Vector Asset

android-studio-new-vector-asset

5. Click on the launcher icon to browse Material Icons

android-studio-vector-asset-dialog

6. Select an icon and click on ok

choosing-vector-icon

7. Review the name of the file then click on next.

vector-asset-preview

8. Now Vector Asset Studio will show the location about where the file is being saved, review it and click on finish.

9. The drawable folder will now consist of a newly created file (In my case ic_flight_takeoff)

below is the file code –


<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="35dp"
        android:height="35dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FFe29069"
        android:pathData="M2.5,19h19v2h-19zM22.07,9.64c-0.21,-0.8 -1.04,-1.28 -1.84,-1.06L14.92,10l-6.9,-6.43 -1.93,0.51 4.14,7.17 -4.97,1.33 -1.97,-1.54 -1.45,0.39 1.82,3.16 0.77,1.33 1.6,-0.43 5.31,-1.42 4.35,-1.16L21,11.49c0.81,-0.23 1.28,-1.05 1.07,-1.85z"/>
</vector>


You can modify the width and height of the vector as per your requirement (by default it stays as 24dp), a vector may consist of one or more paths. A path may have many attributes among which fillColor and pathData are the most important. fillColor attribute defines the color of the path, it must be a color attribute (hash code in #aarrggbb, or may also point to a color resource). pathData defines the path shape. In this case I’ve modified the vector width, height and path fillColor.

2.2 Creating VectorDrawable from SVG or PSD

Now we have created vectorDrawable from Material Icon, what if we want a separate icon? We can create it from SVG or PSD, below are the procedure, but it also has some restrictions you can check out here – https://developer.android.com/studio/write/vector-asset-studio.html#PSD (though the restriction listed here for PSD, it applies to SVG also).

10. In the project Right click on the drawable directory

11. Go to New ⇒ Vector Asset

12. Click on the radio button saying “Local File (SVG, PSD)”

android-studio-choosing-vector-asset

13. Click on the browse icon and navigate to your SVG or PSD file to select it

android-studio-choosing-svg

14. After selecting click ok

15. Verify the image in preview and click Next ⇒ Finish.

android-studio-choosing-svg

below is the file code generated from svg


<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="100dp"
    android:height="100dp"
    android:viewportHeight="512.0"
    android:viewportWidth="512.0">
    <path
        android:fillColor="#273B7A"
        android:pathData="M256,256m-256,0a256,256 0,1 1,512 0a256,256 0,1 1,-512 0" />
    <path
        android:fillColor="#121149"
        android:pathData="M506.4,309.5L300.1,103.3l-62.2,113.4l2.3,44.8l82.5,82.5l-3.4,3.4l-35.8,-35.8l-45.6,2.9h-64.7l-66.7,105.5l83.6,83.6C211.2,509 233.2,512 256,512C379,512 481.8,425.2 506.4,309.5z" />
    <path
        android:fillColor="#FFEDB5"
        android:pathData="M401.6,290.3c-3.3,-4.6 -9.3,-6.4 -14.6,-4.4c-0.1,0 -0.2,0.1 -0.2,0.1l-89.6,29.8c0,0.7 0,1.4 -0,2.2c-0.7,11.4 -9.6,20.6 -21,21.8l-54,5.6c-3.4,0.4 -6.5,-2.1 -6.8,-5.5c-0.4,-3.4 2.1,-6.6 5.5,-6.8l54,-5.6c5.3,-0.6 9.5,-4.9 9.8,-10.2c0.2,-2.9 -0.8,-5.8 -2.7,-8c-1.9,-2.2 -4.6,-3.5 -7.6,-3.7l-71.7,-4.7c-8.1,-0.5 -16,1.3 -23.1,5.1L85,358l25.6,51.6l23.8,-20.7c10.1,-8.8 23.5,-12.6 36.7,-10.4l79.4,13.2c14.6,1.9 29.1,-1.7 41.1,-10.2l108.1,-74.5C404.5,302.8 405.4,295.5 401.6,290.3z" />
    <path
        android:fillColor="#FEE187"
        android:pathData="M274.9,327.4c5.3,-0.6 9.5,-4.9 9.8,-10.2c0.2,-2.9 -0.8,-5.8 -2.7,-8c-1.9,-2.2 -4.6,-3.5 -7.6,-3.7l-15.9,-1v24.7L274.9,327.4z" />
    <path
        android:fillColor="#FEE187"
        android:pathData="M401.6,290.3c-3.3,-4.6 -9.3,-6.4 -14.6,-4.4c-0.1,0 -0.2,0.1 -0.2,0.1l-89.6,29.8c0,0.7 0,1.4 -0,2.2c-0.7,11.4 -9.6,20.6 -21,21.8l-17.7,1.8v50.6c11.8,-0.1 23.3,-3.8 33.1,-10.7l108.1,-74.5C404.5,302.8 405.4,295.5 401.6,290.3z" />
    <path
        android:fillColor="#FFC61B"
        android:pathData="M317.4,146c0,-34.7 -28.9,-62.8 -63.9,-61.4c-31.4,1.2 -57.1,26.5 -58.9,57.9c-1.2,21.6 8.7,40.9 24.6,52.7c10.1,7.6 16.3,19.2 16.3,31.9v21.3c0,11.3 9.2,20.5 20.5,20.5l0,0c11.3,0 20.5,-9.2 20.5,-20.5V227.4c0,-12.8 6.2,-24.6 16.5,-32.3C307.8,183.9 317.4,166 317.4,146z" />
    <path
        android:fillColor="#EAA22F"
        android:pathData="M255.4,84.6v184.2c0.2,0 0.4,0 0.6,0c11.3,0 20.5,-9.2 20.5,-20.5V227.4c0,-12.8 6.2,-24.6 16.5,-32.3c14.9,-11.2 24.5,-29 24.5,-49.1C317.4,111.9 289.6,84.3 255.4,84.6z" />
    <path
        android:fillColor="#A6A8AA"
        android:pathData="M235.5,227.9v20.5c0,11.3 9.2,20.5 20.5,20.5l0,0c11.3,0 20.5,-9.2 20.5,-20.5v-20.5L235.5,227.9z" />
    <path
        android:fillColor="#808183"
        android:pathData="M255.4,227.9v40.9c0.2,0 0.4,0 0.6,0c11.3,0 20.5,-9.2 20.5,-20.5v-20.5L255.4,227.9z" />
    <path
        android:fillColor="#FF5419"
        android:pathData="M244.2,183.8c-1.1,0 -2.3,-0.3 -3.3,-1.1c-2.5,-1.8 -3,-5.3 -1.2,-7.8l17.1,-23.4H244.2c-2.1,0 -4,-1.2 -5,-3.1c-1,-1.9 -0.8,-4.1 0.5,-5.8l23.6,-32.3c1.8,-2.5 5.3,-3 7.8,-1.2c2.5,1.8 3,5.3 1.2,7.8L255.2,140.4h12.6c2.1,0 4,1.2 5,3.1c1,1.9 0.8,4.1 -0.5,5.8l-23.6,32.3C247.6,183 245.9,183.8 244.2,183.8z" />
    <path
        android:fillColor="#C92F00"
        android:pathData="M272.3,117c1.8,-2.5 1.3,-6 -1.2,-7.8c-2.5,-1.8 -6,-1.3 -7.8,1.2l-7.9,10.8v18.9L272.3,117z" />
    <path
        android:fillColor="#C92F00"
        android:pathData="M267.8,140.4h-12.4v11.2h1.4l-1.4,1.9v18.9l16.9,-23.1c1.2,-1.7 1.4,-3.9 0.5,-5.8C271.8,141.6 269.9,140.4 267.8,140.4z" />
    <path
        android:fillColor="#D35933"
        android:pathData="M66.1,355.1l32.5,-22.2l40.5,64.7l-32.5,22.2z" />
    <path
        android:fillColor="#B54324"
        android:pathData="M139.1,397.6l-20.5,-32.8l-32.4,22.5l20.4,32.6z" />
</vector>

3. Using VectorDrawable

We have successfully added VectorDrawables to the project, now it’s time to use them.

16. Open the layout file of main activity (activity_main.xml) and add the below xml. This layout contains shows how to use VectorDrawable with ImageView and other Views (as background) which is explained later in this tutorial.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="info.androidhive.vectordrawable.MainActivity">

    <ImageView android:id="@+id/ic_logo"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="30dp"
        android:layout_marginTop="30dp"
        app:srcCompat="@drawable/ic_light_bulb" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:gravity="center_horizontal"
        android:text="Tap on icon to change tint color" />

    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/ic_android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="30dp" />

    <android.support.v7.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="20dp"
        android:drawableLeft="@drawable/ic_flight_takeoff"
        android:gravity="center_horizontal"
        android:text="TextView with Vector Drawable" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Radio button with vector drawable icons" />

    <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:showDividers="middle"
        android:orientation="horizontal"
        android:gravity="center">

        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />

        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />

        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />

        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />

        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />

    </RadioGroup>


</LinearLayout>



The above layout generates a screen something like this.

android-working-with-vector-drawables

3.1 Using VectorDrawable with ImageView from xml

So let us start with a simple ImageView, and even simpler by assigning the VectorDrawable to the ImageView through xml layout.


<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   app:srcCompat="@drawable/ic_light_bulb"/>

As you can see, we used app:srcCompat instead of android:src, so that the support library can do the rest to display the image seamlessly on all versions of android. (The support library converts VectorDrawables to raster graphics automatically on android versions below 5.0 – API 21, details are here). So it was that easy.

3.2 Using VectorDrawable with ImageView from Java

Now Let us do the same thing with Java code, i.e. assigning VectorDrawable to ImageView through Java Code.

17. Add another Vector Drawable (name it ic_android.xml) with the steps mention in section 2.1 or 2.2, you can also create a file with that name and paste the below code.


<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="50dp"
    android:height="50dp"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path
        android:fillColor="@color/colorPrimaryDark"
        android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z" />
</vector>


18. Open MainActivity.java and paste the below code.


package info.androidhive.vectordrawable;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.AppCompatImageView;
import android.view.View;

import java.util.Random;

public class MainActivity extends AppCompatActivity {

    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final AppCompatImageView icAndroid = (AppCompatImageView) findViewById(R.id.ic_android);
        icAndroid.setImageResource(R.drawable.ic_android);

        icAndroid.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Random rnd = new Random();
                int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
                icAndroid.setColorFilter(color);
            }
        });
    }
}


Now, let me explain the code line by line.

19. For using VectorDrawable from java or to use it as background (in xml also) you need to intimate AppCompatDelegate to enable compat vector from resource. Below is the code for that.

static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

20. Whenever you are going to use VectorDrawable from java or to use it as background (in xml also) remember to use AppCompatView instead of normal view, here I have used AppCompatImageView, please also refer to the layout we created before.

21. Now assign the VectorDrawable as src or background as you do it normally, AppCompat will take care of the rest.

22. We have added some flavors to it, We implemented OnClickListener on the ImageView to set random color filter on it, upon click.

3.3 Using VectorDrawable as Drawable with TextView

You may want to use VectorDrawable as background or as compound drawable with TextView, so below is an example.

<android.support.v7.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="20dp"
        android:drawableLeft="@drawable/ic_flight_takeoff"
        android:gravity="center_horizontal"
        android:text="TextView with Vector Drawable" />

As you can see from above code we have used a VectorDrawable in the drawableLeft attribute of android.support.v7.widget.AppCompatTextView, we can also do it from the java code using AppCompatTextView#setCompoundDrawables.

3.4 Using VectorDrawable to Customise RadioButton

So far the use was straightforward, what if you want to customise a RadioButton or CheckBox while using VectorDrawable? Now lets see that. If you go through the layout we created, once again then you can find that a RadioGroup which contains a series of AppCompatRadioButton, all the AppCompatRadioButtons there uses @drawable/radio_selector as background, below is the code for that.


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@drawable/ic_star"
        android:state_checked="true"
        android:state_pressed="true" />
    <item
        android:drawable="@drawable/ic_star"
        android:state_pressed="true" />
    <item
        android:drawable="@drawable/ic_star"
        android:state_checked="true" />
    <item
        android:drawable="@drawable/ic_star_border" />
</selector>

As you can see this is a selector drawable as usual, the only difference is that it refers to VectorDrawables (vector image resources) instead of raster image resources. The remaining is taken care by android.support.v7.widget.AppCompatRadioButton itself as mentioned earlier (remember to use AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) for that also, even if you don’t consider backward compatibility).

The final output looks something like this.

android-working-with-vector-drawables

I hope this article gave you a very good overview about Using Vector Drawables in Android. Feel free to ask any queries / doubts in comments section below.

Rivu Chakraborty is a Sr. Tech. Member of Institution of Engineers(India), Diploma holder Engineer in Computer Science. He is presently at MaxMobility Pvt. Ltd. as a Sr. Software Engineer (Android)
Author

Rivu Chakraborty is a Sr. Tech. Member of Institution of Engineers(India), Diploma holder Engineer in Computer Science. He is presently at MaxMobility Pvt. Ltd. as a Sr. Software Engineer (Android)

Comments are closed.