Ben
Ben

Reputation: 1849

Change vector asset color programmatically when clicked

I have created the following vector asset and inserted it into an Imagebutton.

enter image description here

I had like that the heart will change its color to red once it was clicked and return to transparent once it was clicked again.

I couldn't find any place that describes how to change the color of the whole heart. The closest solution I found was:

    ibWhishlist.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ibWhishlist.setColorFilter(getResources().getColor(R.color.colorRed));
        }
    });

However, it changes only the border of the heart and not the whole shape.

Thank you

SOLUTION:

Eventually what I used to solve this problem is to create as follows:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_selected="true"
        android:drawable="@drawable/ic_favorite_red_24dp" />
    <item
        android:drawable="@drawable/ic_favorite_black_24dp" />
</selector>

and inside my code:

ibWhishlist.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ibWhishlist.setSelected(!ibWhishlist.isSelected());
        if (ibWhishlist.isSelected()) {
            //Handle selected state change
        } else {
            //Handle de-select state change
        }
    }
});

Upvotes: 1

Views: 6006

Answers (3)

Abed
Abed

Reputation: 5217

The simplest way to solve this problem, if you want to change minor things like fill/stroke color or stroke width at runtime, is two have two versions of the same vector image with these changes, for example, one of them has only stroke color and the other one is filled:

ic_heart_stroked.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:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"
            android:strokeWidth="1"
            android:strokeColor="#000" />
</vector>

ic_heart_filled.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:fillColor="#FF000000"
        android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
</vector>

Then in your code, switch between the two files when the user clicks:

  ibWhishlist.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               ibWhishlist.setImageResource(R.drawable.ic_heart_filled);
            }
        });

Another way is to use one of the ready-made libraries. RichPathAnimator is one of the best libraries, it supports changing vector color, stroke width, and even animate vector graphics at runtime.

How to use it? First, add the library dependency to your app build.gradle. Then in your vector.xml give a name to the path that you want to change so:

<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="heartPath1"
            android:fillColor="#00000000"
            android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"
            android:strokeWidth="1"
            android:strokeColor="#000" />
</vector>

In your layout replace Imagebutton with com.richpath.RichPathView and inside the vector, attribute pass your vector resource in that tag:

<com.richpath.RichPathView
        android:id="@+id/heartView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:vector="@drawable/ic_heart" />

In your Activity get a reference to the richpathview then call findRichPathByName(YOUR_PATH_NAME)

RichPathView heartView = findViewById(R.id.heartView);
//Providing the path name that you add to your vector,
//in our example it's 'heartPath1'.
RichPath path= heartView.findRichPathByName("heartPath1");
//Set on heart path click listener.
path.setOnPathClickListener(new RichPath.OnPathClickListener() {
       @Override
       public void onClick(RichPath richPath) {
       //Change the path color.
       richPath.setFillColor(Color.RED);
       //Change stroke width to zero.
       richPath.setStrokeWidth(0);
    }
});

If you don't want to use RichPathView instead of your ImageView or ImageButton, and you want to change some things in your vector path, then consider using VectorChildFinder.

Upvotes: 4

Sep
Sep

Reputation: 371

public static Drawable updateDrawableVector(int resId, Context context, int color) {
        Drawable drawable = context.getResources().getDrawable(resId);
        drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
        return drawable;
    }

Upvotes: 0

Piyush
Piyush

Reputation: 571

Programmatically you can change the color of vector icon, but you can use only a single color. Since in your case heart icon filling background color, that's why your code is changing the border of icon.

you can take 2 vectors drawable to solve your problem (just one possibility)

You can check this link as well, How to change color of vector drawable path on button click

Upvotes: 0

Related Questions