How to change color of vector drawable path on button click
Asked Answered
J

9

53

With the new android support update, vector drawables get backward compatibility. I have a vector image with various paths. I want the color of the paths to change on click of a button or programmatically based on an input value. Is it possible to access the name parameter of the vector path? And then change the color.

Joellyn answered 25/2, 2016 at 10:48 Comment(1)
you can tint the whole vector, but not single path componentsBareheaded
G
45

Use this to change a path color in your vector drawable

VectorChildFinder vector = new VectorChildFinder(this, R.drawable.my_vector, imageView);

VectorDrawableCompat.VFullPath path1 = vector.findPathByName("path1");
path1.setFillColor(Color.RED); 

Library is here: https://github.com/devsideal/VectorChildFinder

Gladstone answered 3/2, 2018 at 7:48 Comment(4)
But no longer in Maven?Allusive
Ahh, I did not have jitpack.io added. It now finds it, cheers!Allusive
Isn't there a way to change the color of something within the VectorDrawable, without a library? Isn't there anything in the support library for this?Sagunto
@Gladstone I couldnot find the way to change path inside group. Any solutions?Incombustible
W
61

The color of the whole vector can be changed using setTint.

You have to set up your ImageView in your layout file as this:

<ImageView
    android:id="@+id/myImageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tint="@color/my_nice_color"
    android:src="@drawable/ic_my_drawable"
    android:scaleType="fitCenter" />

Then to change the color of your image:

DrawableCompat.setTint(myImageView.getDrawable(), ContextCompat.getColor(context, R.color.another_nice_color));

Note: myImageView.getDrawable() gives nullpointerexception if the vector drawable is set to the imageView as background.

Warbeck answered 4/4, 2016 at 10:44 Comment(5)
This sets tint to the whole drawable but not a specific path of the vector drawable.Joellyn
android:tint must be set after setting android:srcSissy
What about Button? There is no android:tint for Button.Subcortex
I dont know the scope of this operation but I had a problem in Activity scope; when I replace Fragments, tint change doesnt invalidate. I solved my issue with imageView.setColorFilterTatia
Even if you have only one path, tint changes both fill AND stroke.Sokotra
G
45

Use this to change a path color in your vector drawable

VectorChildFinder vector = new VectorChildFinder(this, R.drawable.my_vector, imageView);

VectorDrawableCompat.VFullPath path1 = vector.findPathByName("path1");
path1.setFillColor(Color.RED); 

Library is here: https://github.com/devsideal/VectorChildFinder

Gladstone answered 3/2, 2018 at 7:48 Comment(4)
But no longer in Maven?Allusive
Ahh, I did not have jitpack.io added. It now finds it, cheers!Allusive
Isn't there a way to change the color of something within the VectorDrawable, without a library? Isn't there anything in the support library for this?Sagunto
@Gladstone I couldnot find the way to change path inside group. Any solutions?Incombustible
M
8

There are several ways of doing the same stuff, but this works for both Vector Drawables as well as SVG (Local/Network).

imageView.setColorFilter(ContextCompat.getColor(context, 
R.color.headPink), android.graphics.PorterDuff.Mode.SRC_IN);

(change R.color.headPink with color of your choice)

Mechanistic answered 7/2, 2018 at 12:15 Comment(1)
The question is about changing the color of a specific element, not the whole drawable.Broaddus
T
5

You can change the color of individual path at runtime, without using reflection.

VectorMaster introduces dynamic control over vector drawables. Each and every aspect of a vector drawable can be controlled dynamically (via Java instances), using this library.

Just add the following dependency in your app's build.gradle

dependencies {
    compile 'com.sdsmdg.harjot:vectormaster:1.0.9'
}

In your case you need a simple color change:

Vector example: your_vector.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
<path
    android:name="outline"
    android:pathData="M20.84,4..."
    android:strokeColor="#5D5D5D"
    android:fillColor="#00000000"
    android:strokeWidth="2"/>

XML:

<com.sdsmdg.harjot.vectormaster.VectorMasterView
    android:id="@+id/your_vector"
    android:layout_width="150dp"
    android:layout_height="150dp"
    app:vector_src="@drawable/your_drawable" />

Java:

VectorMasterView heartVector = (VectorMasterView) 
findViewById(R.id.your_drawable);

// find the correct path using name
PathModel outline = heartVector.getPathModelByName("outline");

// set the stroke color
outline.setStrokeColor(Color.parseColor("#ED4337"));

// set the fill color (if fill color is not set or is TRANSPARENT, then no fill is drawn)
outline.setFillColor(Color.parseColor("#ED4337"));

From: https://github.com/harjot-oberai/VectorMaster, licensed under MIT.

You have now full control over vector drawables.

Tova answered 7/11, 2017 at 16:10 Comment(4)
Very nice. My svg doesn't use names and it would be inpractical to edit and add names by hand.Iis it possible getPathModel by index in array?Amblyopia
You can but you need at least a group name: the group containing your paths, e.g: GroupModel groupModel = getVectorMasterDrawable().getGroupModelByName("groupName"); ArrayList<PathModel> pathModelArrayList = groupModel.getPathModels();Tova
@JeRoll, By any chance I can get a Drawable after setting the path color, at present I set the imageview as hidden and taken drawable = imageView.getDrawable()Rodl
Note that VectorMaster doesn't render some VectorDrawable resources well: github.com/harjot-oberai/VectorMaster/issues/32Sagunto
Q
3

You can use this method to change color in lower API to change vector color in fragment

int myVectorColor = ContextCompat.getColor(getActivity(), R.color.colorBlack);
                    myButton.getIcon().setColorFilter(myVectorColor, PorterDuff.Mode.SRC_IN);

in place of getActivity you should use MainActivity.this for changing vector color in activity

Quadrinomial answered 3/7, 2017 at 17:57 Comment(1)
The question is about changing the color of a specific element, not the whole drawable.Broaddus
V
2

Check my answer on this other question: https://mcmap.net/q/57313/-change-fillcolor-of-a-vector-in-android-programmatically.

It is a great idea on how to manage this by using Themes and parameterizing the paths in order to be able to set them dynamically.

Varices answered 17/7, 2016 at 5:4 Comment(0)
C
0

As stated by @Eyal in this post https://mcmap.net/q/57314/-programmatically-update-android-vector-drawable

You cannot change the color of individual path at runtime. Looking at the source code of VectorDrawableCompat, the only method to expose the inner element by name is getTargetByName which is present in inner private state class VectorDrawableCompatState of VectorDrawableCompat.

Since it is a package private (default) - you can't use it (unless you use reflection).

Crosse answered 25/5, 2016 at 9:14 Comment(2)
@Shubral, can you please elaborate with code on how reflection can be used to achieve this? It may take time but would help loads of people.Joellyn
I actually tried to use reflection, and even though I've succeeded reaching the function, it returned just null... Can you please show how to do it?Sagunto
N
0

This can be done through Java reflection. First reflect call VectorDrawable.getTargetByName or VectorDrawableCompat.getTargetByName method to get VFullPath:

Object path = ReflectUtil.invoke(vectorDrawable, "getTargetByName", new Class[]{String.class}, new Object[]{pathName});

Then Reflect calls the VFullPath.setFillColor method to set the color:

ReflectUtil.invoke(path, "setFillColor", new Class[]{int.class}, new Object[]{color});
Nautch answered 7/6, 2023 at 13:27 Comment(0)
E
-2
DrawableCompat.setTint(imageView.getDrawable(),ContextCompat.getColor(getApplicationContext(), R.color.colorAccent));
Evalyn answered 28/7, 2020 at 6:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.