How to use VectorDrawables in Android API lower than 21?

JavaAndroidSvgAndroid Vectordrawable

Java Problem Overview


I am working on an Android project and I chose <vector> to display icon because it is adaptable and dynamically, however, I just can run this app on devices running Android, which have API 21 or higher. My question is how can I use <vector> on lower Android version i.e. API 14 or kind of. Thanks!

<!-- drawable/ic_android_debug_bridge.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="48dp"
    android:width="48dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path android:fillColor="@color/primaryColorDark"
        android:pathData="M15,9A1,1 0 0,1 14,8A1,1 0 0,1 15,7A1,1 0 0,1 16,8A1,1 `0 0,1 15,9M9,9A1,1 0 0,1 8,8A1,1 0 0,1 9,7A1,1 0 0,1 10,8A1,1 0 0,1 9,9M16.12,4.37L18.22,2.27L17.4,1.44L15.09,3.75C14.16,3.28 13.11,3 12,3C10.88,3 9.84,3.28 8.91,3.75L6.6,1.44L5.78,2.27L7.88,4.37C6.14,5.64 5,7.68 5,10V11H19V10C19,7.68 17.86,5.64 16.12,4.37M5,16C5,19.86 8.13,23 12,23A7,7 0 0,0 19,16V12H5V16Z" /></vector>

Java Solutions


Solution 1 - Java

With the support library 23.2, the true support for Vector Drawables has been provided all the way down to API v7. It is recommended to disable the previous version of the support, which rendered PNG during build-time, by adding

// Gradle Plugin 2.0+
 android {
   defaultConfig {
     vectorDrawables.useSupportLibrary = true
    }
 }

to the build.gradle file.

The implementation is fairly simple. Just use the new srcCompat attribute on Drawables (under app namespace!):

<ImageView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:srcCompat="@drawable/ic_add" />    // <= this is new

Vector Drawables are also supported in cases like TextView's drawableLeft property.

Source: library announcement

However, I would still recommend something like Iconics library, AndroidSVG, or another font-icon or SVG solution for the full SVG-standand vector support.

Solution 2 - Java

VectorDrawable are supported pre-Lollipop via the Support Library, but the way to use them depends on the version of Support Library you have. And it may not work in all cases.

I've made this diagram to help (valid for Support Library 23.4.0 to - at least - 25.1.0).

VectorDrawable cheatsheet

Solution 3 - Java

I found solution! For those who search solution with TextView and other "android" namespace attributes. First of all this is necessary:

android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
    }  
 }

And in application class define this:

    @Override
    public void onCreate() {
        super.onCreate();
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

Now you can use app:srcCompat="@drawable/ic_add" but if you try to use android:background= or android:drawableLeft= it will crash app with "Error inflating" exception.

We can create wrapped drawable ic_add_wrapped.xml for this vector:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_add"/>
</layer-list>

And now it will work with any property like drawableLeft or background. Just set android:drawableLeft="@drawable/ic_add_wrapped.xml". WARNING! THIS IS A WORKAROUND SOLUTION. So you use it for your own risk.

Solution 4 - Java

Vector Drawables are now backward compatible, it's just a matter of upgrading your gradle version to 1.4.0-beta3 or higher, and upgrade your IDE :

> We are also excited to offer backwards compatibility for your vector > assets in Android Studio 1.4. Once you have a vectorDrawable image in > your res/drawable, the Gradle plugin will automatically generate > raster PNG images for API level 20 and below during build time. This > means you only need to update and maintain your vector asset for your > app project and Android Studio can take care of image conversion > process.

http://android-developers.blogspot.com.uy/2015/09/android-studio-14.html

Solution 5 - Java

you need use android Support Repository 30+ if you using android studio and need android support library 23.2.1+ if using Eclipse.

check your build.gradle (project) if using version 2.0+ add below code in your build.gradle (app)

// Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
    }  
 }

and: if using version 1.5 add below in your build.gradle(app)

// Gradle Plugin 1.5  
 android {  
   defaultConfig {  
     generatedDensities = []  
  }  

  // This is handled for you by the 2.0+ Gradle Plugin  
  aaptOptions {  
    additionalParameters "--no-version-vectors"  
  }  
 }  

here is sample code for use vector icon:

<ImageView  
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content"  
  app:srcCompat="@drawable/ic_add"
  tools:ignore="MissingPrefix" />

or

<ImageButton
  android:layout_width="wrap_content"
  android:background="@android:color/transparent"
  app:srcCompat="@drawable/camera"
  tools:ignore="MissingPrefix"
  android:layout_height="wrap_content"/>

Vector Drawables are also supported in cases like TextView's drawableLeft property. but it worked api 22+ to me and i still dont know how it will work for low api.

Also keep in mind if you want to be compatible below API 21:

  • you cannot use the android:background property in xml or View.setBackgroundResource() function. You need to use the View.setBackground().
  • you cannot use the svg-s in StateListDrawable xml-s or other xml drawables, you have to generate them programmatically.
  • you cannot use svg-s in case of notifications.

Solution 6 - Java

When you need to add VectorDrawable (created from SVG) programatically, you can do it like this:

icon = VectorDrawableCompat.create(resources, R.drawable.ic_map_black_24dp, null)

Solution 7 - Java

For lower version compatible,

  1. add the below in gradle,

     android {  
        defaultConfig {  
          vectorDrawables.useSupportLibrary = true  
         }  
      }
    
  2. add the below code in onCreate() in your application class,

     @Override
         public void onCreate() {
             super.onCreate();
             AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
         }
    
  3. In xml for imageView,

     <ImageView
         android:id="@+id/imageViewMessage"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:background="@color/transparent"
         app:srcCompat="@drawable/ic_success"/>
    
  4. If you want to change the image source programmatically use this,

     imageView.setImageResource(R.drawable.ic_launcher);
    

Solution 8 - Java

I had an issue where my vector images would show up but would be completely black, this was due to an issue where you can't reference color resources in the vector xml file.

So instead of @color/primaryColorDark you have to use the actual color e.g. #212121

Solution 9 - Java

Just to make @2Dee's answer complete:

VectorDrawable cannot be used on API 20 and lower. The official method generates pngs, which then become BitmapDrawables, which breaks the idea of vector graphics.

Personally I prefer svg's over xml vectors:

  • such graphics can be exported right from Illustrator or other popular software
  • svg supports transformations, text, masks and other things properly
  • true scallable vector graphics on all platforms
  • smaller size and faster builds

To use vector graphics you can try https://github.com/BigBadaboom/androidsvg . It's an svg reader and svg-compatible ImageView.

Solution 10 - Java

If you are using Android Studio 3.0.0 you can set

android.enableAapt2=false 

in gradle.properties

https://www.reddit.com/r/androiddev/comments/6mj8di/android_studio_30_canary_6_released/

Solution 11 - Java

You can use programatically ..to set drawableLeft to your editText or textView

like

Drawable tick_drawable = VectorDrawableCompat.create(getResources(), R.drawable.green_tick, null);
    if (tick_drawable != null) {
        tick_drawable.setBounds(0, 0, tick_drawable.getIntrinsicWidth(),tick_drawable.getIntrinsicHeight());
    }

And to drawable left like this..

editText.setCompoundDrawables( tick_drawable , null, null, null );

Solution 12 - Java

after setting vectorDrawables.useSupportLibrary = true in gradle default and AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); in activity on create

To avoid crash with android:drawableleft in Textview, set drawble left to the textview programitically for examlple:

 textview.setCompoundDrawablesWithIntrinsicBounds(R.drawable.movie, 0, 0, 0);

Solution 13 - Java

I also found the same issue. And I did:

> vectorDrawables.useSupportLibrary = true > > AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); > > textview.setCompoundDrawablesWithIntrinsicBounds(R.drawable.movie, 0, 0, 0);

It is good. But after that, I got an error that the resource not found.
So I found it's better to add a vector image according to the SDK version.

Finally, this solution became good is for me:-

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    textview.setCompoundDrawablesWithIntrinsicBounds(null, null, AppCompatResources.getDrawable(this, R.drawable.movie), null);
} else {
    textview.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.movie, 0);
}
  • I hope, it will help someone.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioniamatsundere181View Question on Stackoverflow
Solution 1 - JavaAlen SiljakView Answer on Stackoverflow
Solution 2 - JavaDavid FerrandView Answer on Stackoverflow
Solution 3 - JavaYazon2006View Answer on Stackoverflow
Solution 4 - Java2DeeView Answer on Stackoverflow
Solution 5 - Javamehrdad khosraviView Answer on Stackoverflow
Solution 6 - JavacVoroninView Answer on Stackoverflow
Solution 7 - JavaKavya ShravanView Answer on Stackoverflow
Solution 8 - JavaMark O'SullivanView Answer on Stackoverflow
Solution 9 - JavaZielonyView Answer on Stackoverflow
Solution 10 - JavaPatrick HendersonView Answer on Stackoverflow
Solution 11 - JavaSantanu SurView Answer on Stackoverflow
Solution 12 - JavaAfjalur Rahman RanaView Answer on Stackoverflow
Solution 13 - JavaBhaven ShahView Answer on Stackoverflow