24

I have been using the Android Asset Studio to generate vector drawables from SVG files exported from Zeplin for a while and except a few times, it works fine. But today I got this exception when I was trying to use a generated vector drawable.

android.view.InflateException: Binary XML file line #0: Error inflating class <unknown>

And in the same stacktrace:

Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #0: invalid drawable tag gradient

I do not know a lot about Vector drawables and SVGs in Android. Are gradients not supported in Vector drawables? Is there any fix for this issue or do I need to use PNGs?

I am using Support Library version:

com.android.support:support-v4:26.1.0

I am using

Android Studio 3.0

Here is the VectorDrawable file generated by Android Asset Studio:

<vector 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="360dp"
    android:height="110dp"
    android:viewportWidth="360.0"
    android:viewportHeight="110.0">
    <path
        android:pathData="M82,46H0v64h360V46h-81.88v-0.3h-26.21c-14.25,0 -38.69,-6.2 -46.95,-25.93C200.99,10.25 193.27,0.52 180,0.47c-13.27,-0.05 -20.04,9.24 -24.75,19.3 -8.22,17.55 -24.66,26.19 -49.34,25.93H82V46z"
        android:fillType="evenOdd">
        <aapt:attr name="android:fillColor">
            <gradient 
                android:startY="0.41999998688697815" 
                android:startX="0.0" 
                android:endY="110.0" 
                android:type="linear" 
                android:endX="360.0">
                <item android:offset="0.0" android:color="#FFCB09FF" />
                <item android:offset="1.0" android:color="#FF8A06FF" />
            </gradient>
        </aapt:attr></path>
</vector>

Link to original SVG file: https://drive.google.com/file/d/1Lj62xJv5IpYR5Lle7w1kMsFXh6y5PijK/view?usp=sharing

SVG contents when opened on Sublime:

<svg xmlns="http://www.w3.org/2000/svg" width="360" height="110" viewBox="0 0 360 110">
    <defs>
        <linearGradient id="a" x1="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#CB09FF"/>
            <stop offset="100%" stop-color="#8A06FF"/>
        </linearGradient>
    </defs>
    <path fill="url(#a)" fill-rule="evenodd" d="M82 46H0v64h360V46h-81.876v-.299h-26.208c-14.25 0-38.69-6.198-46.946-25.93C200.99 10.252 193.27.52 180 .474c-13.27-.047-20.04 9.238-24.75 19.295-8.217 17.55-24.662 26.194-49.336 25.931H82V46z"/>
</svg>
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Praveen Singh
  • 2,499
  • 3
  • 19
  • 29
  • 1
    This may be [this bug in Android Studio](https://issuetracker.google.com/issues/67083076). Do you have an SVG that you can publish somewhere that reproduces this problem? Also, what version of Android Studio are you using? – CommonsWare Dec 17 '17 at 11:51
  • Thanks for the bug tracker Mark, I have added the SVG as well as Android Studio version to the question itself. – Praveen Singh Dec 17 '17 at 12:01
  • 1
    Sorry, I meant the input SVG, not the vector asset output. – CommonsWare Dec 17 '17 at 12:22
  • Try removing the ` ... ` tag. – Phantômaxx Dec 17 '17 at 13:32
  • @CommonsWare, Here is the SVG file: https://drive.google.com/file/d/1Lj62xJv5IpYR5Lle7w1kMsFXh6y5PijK/view?usp=sharing – Praveen Singh Dec 17 '17 at 13:39
  • 1
    OK, my converted asset looks like yours. But I used the asset in an `ImageView` in a `minSdkVersion 21` project and it ran fine on a Nexus 9 running Android 7.1. What version of Android are you testing on where it is crashing? – CommonsWare Dec 17 '17 at 13:44
  • @CommonsWare, So I just tested on a 8.0.0 emulator and it works fine. It is still crashing on a 5.1 device though. – Praveen Singh Dec 17 '17 at 13:58
  • @NoiseGenerator, after removing the tag, the crash is gone, but the asset is not being rendered at all now. Both in the Android studio preview as well as on device. – Praveen Singh Dec 17 '17 at 13:59
  • Did you try removing the whole gradient? – Phantômaxx Dec 17 '17 at 14:02
  • Just tried removing the whole gradient also, nothing gets rendered. – Praveen Singh Dec 17 '17 at 14:07
  • Whoever has downvoted this question. Can you please leave a comment explaining the reason for downvote? – Praveen Singh Dec 17 '17 at 14:09
  • 3
    OK, I am considering this to be a separate bug. I took the liberty of using your SVG to create a sample project and [filed a bug report](https://issuetracker.google.com/issues/70760059). At minimum, the Vector Asset Wizard should be handling this better, at least warning us if the resulting vector drawable will not work to our `minSdkVersion`. My assumption is that `` support was only added in Android 7.0 (as the asset from your SVG works there). – CommonsWare Dec 17 '17 at 14:33
  • 7
    In terms of a workaround, you could convert the SVG to PNG yourself using some other tool, move the vector drawable from `res/drawable/` to `res/drawable-anydpi-v24/`, and use the Image Asset Wizard to set up PNG versions in the appropriate densities. The vector would be used on Android 7.0, falling back to the PNG on 5.0-6.0. – CommonsWare Dec 17 '17 at 14:36
  • @CommonsWare Thanks for the bug report as well as the workaround solution. – Praveen Singh Dec 17 '17 at 15:00

10 Answers10

25

This solution is working for us in build.gradle

defaultConfig {
vectorDrawables.useSupportLibrary = true
}

and use app:srcCompat instead of android:src when setting a vector drawable with gradient to a ImageView.

Abhishek Bansal
  • 5,197
  • 4
  • 40
  • 69
  • 1
    If you try to use this for an `ImageButton` make sure you use `androidx.appcompat.widget.AppCompatImageButton`! – SqAR.org Oct 29 '20 at 17:42
  • 1
    Also, don't forget to replace android:drawableStart and its companions with compat version of themselves like app:drawableStartCompat. – Arpit J. Jul 31 '21 at 21:31
21

The property android:fillColor is only supported in OS 7.0+ ,

android:fillColor Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list or a gradient color (See GradientColor and GradientColorItem). If this property is animated, any value set by the animation will override the original value. No path fill is drawn if this property is not specified.

for older versions in directory /drawable we can place the vector asset without the gradients, for example:

<vector android:height="24dp" android:viewportHeight="651.95"
    android:viewportWidth="531.48" android:width="24dp"
    xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:pathData="M386.8,30.2c-48.5,0 -76.1,18 -121.1,18s-72.6,-18 -121.1,-18c-87.9,0 -144.7,83.3 -144.7,186 0,92.9 160,350.5 265.7,350.5 112.9,0 265.7,-257.6 265.7,-350.5C531.5,113.5 474.7,30.2 386.8,30.2Z">
        <!--<aapt:attr name="android:fillColor">
            <gradient android:endX="212457.73219299316"
                android:endY="440836.2612554932"
                android:startX="212457.73219299316"
                android:startY="92857.94223999024" android:type="linear">
                <item android:color="#FFFC3A11" android:offset="0.0"/>
                <item android:color="#FFDA0300" android:offset="1.0"/>
            </gradient>
        </aapt:attr>-->
    </path>
    ...
    ...

and inside /drawable-24 directory with gradients:

<vector android:height="24dp" android:viewportHeight="651.95"
    android:viewportWidth="531.48" android:width="24dp"
    xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:pathData="M386.8,30.2c-48.5,0 -76.1,18 -121.1,18s-72.6,-18 -121.1,-18c-87.9,0 -144.7,83.3 -144.7,186 0,92.9 160,350.5 265.7,350.5 112.9,0 265.7,-257.6 265.7,-350.5C531.5,113.5 474.7,30.2 386.8,30.2Z">
        <aapt:attr name="android:fillColor">
            <gradient android:endX="212457.73219299316"
                android:endY="440836.2612554932"
                android:startX="212457.73219299316"
                android:startY="92857.94223999024" android:type="linear">
                <item android:color="#FFFC3A11" android:offset="0.0"/>
                <item android:color="#FFDA0300" android:offset="1.0"/>
            </gradient>
        </aapt:attr>
    </path>
    ...
    ...
Jorgesys
  • 124,308
  • 23
  • 334
  • 268
  • 7
    I'd just like to offer a note. I used Android Studio to create 'New Vector Asset' with an SVG that has gradient in it. I built release APK and looked at the files...inside `build > generated > res > pngs > release` is `drawable-anydpi-v24` and the xml file has been placed there. Similarly inside `drawable-*dpi` at the same level are png bitmaps with the same name. So AS has handled backwards compatibility, there should be no crash in theory, on any device. Yet I have received one crash on LG G4 after one week in a pretty low volume app. – androidguy Aug 04 '18 at 22:37
  • 1
    @androidguy Have you figured out the reason? I'm facing the same issue where crash report received from only LG G4 Android 6.0 device. – BakaWaii Nov 04 '19 at 08:03
  • @BakaWaii I could figure out no reason, but concluded that LG just had awful buggy code. The workaround I implemented was: take the generated PNGs from the path in my earlier comment, copy them to the `drawable-*dpi` folders inside the actual src, and delete the vector .xml inside `drawable` in src. – androidguy Nov 04 '19 at 16:31
8

android:fillColor with gradient only is support for API 24+ (7.0)

ref: https://developer.android.com/reference/android/graphics/drawable/VectorDrawable.html

try add in 'drawable-v24' and the same vector in 'drawable' folder without gradient

HerberthObregon
  • 1,811
  • 19
  • 23
7

I was able to fix this by using

app:srcCompat="@drawable/ic_vector"

instead of

android:src="@drawable/ic_vector"

This was tested on API 22 device

Mohammad Shabaz Moosa
  • 1,515
  • 1
  • 13
  • 20
5

The error caused by android:fillColor attribute; this because:

android:fillColor Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list or a gradient color (See GradientColor and GradientColorItem). If this property is animated, any value set by the animation will override the original value. No path fill is drawn if this property is not specified.

If you want use gradient in version older than 24 you can use a workaround:

-Edit your vector (called for example as drawable/ic_vector.xml):

<vector 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:aapt="http://schemas.android.com/aapt"
android:width="360dp"
android:height="110dp"
android:viewportWidth="360.0"
android:viewportHeight="110.0">
<path
    android:pathData="M82,46H0v64h360V46h-81.88v-0.3h-26.21c-14.25,0 -38.69,-6.2 -46.95,-25.93C200.99,10.25 193.27,0.52 180,0.47c-13.27,-0.05 -20.04,9.24 -24.75,19.3 -8.22,17.55 -24.66,26.19 -49.34,25.93H82V46z"
    android:fillType="evenOdd">
    <!--<aapt:attr name="android:fillColor">
        <gradient 
            android:startY="0.41999998688697815" 
            android:startX="0.0" 
            android:endY="110.0" 
            android:type="linear" 
            android:endX="360.0">
            <item android:offset="0.0" android:color="#FFCB09FF" />
            <item android:offset="1.0" android:color="#FF8A06FF" />
        </gradient>
    </aapt:attr></path>-->

-Create another drawable resource where insert gradient as item:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <gradient 
            android:type="linear"
            android:startColor="#FFCB09FF"
            android:endColor="#FF8A06FF"
            android:angle="270">
        </gradient>
    </shape>
</item>
<item android:drawable="@drawable/ic_vector"/>

Hope I have helped you!

0

Gradient tag in SVG is supported from OS Version 7 and upwards. Try commenting the gradient tag for versions below OS version 7.

0

The solution for me is different, I'll add here hopefully it helps others.

I was using a vector with gradient, here a sample:

<path android:pathData="M69.12,78.34">
<aapt:attr name="android:fillColor">
    <gradient
        android:centerX="69.12"
        android:centerY="78.34002"
        android:gradientRadius="0"
        android:type="radial">
        <item
            android:color="#FFFFF176"
            android:offset="0.41" />
        <item
            android:color="#FFFFC400"
            android:offset="1" />
    </gradient>
</aapt:attr>
</path>

notice the android:gradientRadius="0", the thing is, probably some android versions was reading it as null and crashing with the error of the question.

My workaround was to change to android:gradientRadius="0.1" or any other small number.

ademar111190
  • 14,215
  • 14
  • 85
  • 114
0

for backward compatibility use

app:drawableStartCompat

Manoj Mohanty
  • 372
  • 2
  • 10
0

it seems like this answer has been outdated. The best thing you can resolve this issue is to configure the correct support in build.gradle

    defaultConfig {
       vectorDrawables.useSupportLibrary = true
    }

and recently I created a plugin to make download assets from zeplin and convert them to vector-drawables automatically, you can find more details from here if you want to try it

underwood
  • 199
  • 1
  • 4
-1

Try adding vector support command in your app gradle i.e.

defaultConfig {
    vectorDrawables.useSupportLibrary = true
}

enter image description here

Android Geek
  • 8,956
  • 2
  • 21
  • 35