34

I was looking at the documentation for GradientColor https://developer.android.com/reference/android/R.styleable.html#GradientColor . How can I define a gradient color in XML and apply it to an XML vector drawable?

I have tried in color.xml, styles.xml and within an XML vector drawable.

I get the error " Failed to convert @id/gradclor into a ColorStateList" with:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="120dp"
    android:height="120dp"
    android:viewportWidth="120.0"
    android:viewportHeight="120.0">

    <path
        android:name="play_triangle"
        android:pathData="M 30 30 L 30 90 L 80 60 z"
        android:strokeColor="@id/gradclor"
        android:strokeWidth="5"/>

    <color
        android:name="@+id/gradclor"
        android:startColor="#FFFFFF"
        android:endColor="#00FFFF"
        android:angle="145"/>

</vector>

or "Failed to convert #FFFFFFFF #00FFFFFF 145 into a ColorStateList" when using:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="120dp"
    android:height="120dp"
    android:viewportWidth="120.0"
    android:viewportHeight="120.0">

    <path
        android:name="play_triangle"
        android:pathData="M 30 30 L 30 90 L 80 60 z"
        android:strokeColor="@color/GradientStrokeBorder"
        android:strokeWidth="5"/>

</vector>

with the following in color.xml:

<color name="GradientStrokeBorder">
    <item name="android:startColor">#FFFFFF</item>
    <item name="android:endColor">#00FFFF</item>
    <item name="android:angle">145</item>
</color>
TTransmit
  • 3,270
  • 2
  • 28
  • 43

3 Answers3

54

I've finally made it work. Gradient color feature is not supported yet in Android Studio (current ver is 2.2) so it doesn't help you with autocomplete but marks gradient tag as error instead. Nevertheless, the feature does actually work, I've tested it successfully on Nexus 5X / API 24. Of course, you have to use an API 24+ device because otherwise this feature is not supported by OS.

First, you need to add color resource file like this:

<?xml version="1.0" encoding="utf-8"?>
<gradient xmlns:android="http://schemas.android.com/apk/res/android"
    android:startColor="#FFFFFF"
    android:centerColor="#0000FF"
    android:endColor="#00FFFF"
    android:angle="145"
    android:startX="30"
    android:endX="70"
    android:startY="30"
    android:endY="70"
    android:type="linear"/>

Please pay attention to start/end parameters as I found they are essential for vector gradients.

Place this file into res/color folder under some name. I've named it gradient.xml so the full path is res/color/gradient.xml. After that you can refer to this resource in color attributes, including vector path colors:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="120dp"
    android:height="120dp"
    android:viewportWidth="120.0"
    android:viewportHeight="120.0">

    <path
        android:name="play_triangle"
        android:pathData="M 30 30 L 30 90 L 80 60 z"
        android:strokeWidth="10"
        android:strokeColor="@color/gradient"/>

</vector>

Notice the reference to gradient color resource in strokeColor. Hope this helps!

Alex Kravchenko
  • 961
  • 9
  • 11
  • 16
    Great work. It's worth mentioning that this crashes the app on devices lower than API 24 (7.0) so I put a version referring to the gradient in *res/color/blue_gradient.xml* (`@color/blue_gradient`) in **res/drawable-v24** and a version referring to a regular color in **res/drawable**. – TTransmit Dec 03 '16 at 13:04
  • 3
    I m facing this, "Element gradient must be declared". – Mobikul Webkul Nov 17 '18 at 08:16
  • @MobikulWebkul Same issue. Did you find a solution? – marcorei May 07 '19 at 11:26
  • 2
    Backwards compatibility of vector drawables has been improved since this answer. `vectorDrawables.useSupportLibrary = true` will convert vector drawables to PNGs for APIs below 24. It requires embedding the gradients, colors, dimens in the files without using references. You must then use `app:srcCompat` to refer to the drawable. Below API 21, I think you also need `AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);` in your activity onCreate. https://developer.android.com/guide/topics/graphics/vector-drawable-resources#vector-drawables-backward-solution – TTransmit Jun 21 '19 at 11:25
  • What does the start end parameters do? For the life of me I can not understand it! – distante Jul 28 '20 at 12:49
26

The latest preview of Android (3.1 Canary 6) contains a sample using vector resource with a gradient.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="108dp"
    android:height="108dp"
    android:viewportHeight="108"
    android:viewportWidth="108">
    <path
        android:fillType="evenOdd"
        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="78.5885"
                android:endY="90.9159"
                android:startX="48.7653"
                android:startY="61.0927"
                android:type="linear">
                <item
                    android:color="#44000000"
                    android:offset="0.0" />
                <item
                    android:color="#00000000"
                    android:offset="1.0" />
            </gradient>
        </aapt:attr>
    </path>
    <path
        android:fillColor="#FFFFFF"
        android:fillType="nonZero"
        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1" />
</vector>
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
3

I'm not sure about this, but according to this document:

android:strokeColor Specifies the color used to draw the path outline. 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 outline is drawn if this property is not specified.

if your sdk is <24 it should just be one color.

on the other hand if your sdk is greater than 24, i think that it would be beter to use <gradient/> to fill your path instead of <color/>

pouyan
  • 3,445
  • 4
  • 26
  • 44