'Set android shape color programmatically

I am editing to make the question simpler, hoping that helps towards an accurate answer.

Say I have the following oval shape:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:angle="270"
           android:color="#FFFF0000"/>
    <stroke android:width="3dp"
            android:color="#FFAA0055"/>
</shape>

How do I set the color programmatically, from within an activity class?



Solution 1:[1]

Note: Answer has been updated to cover the scenario where background is an instance of ColorDrawable. Thanks Tyler Pfaff, for pointing this out.

The drawable is an oval and is the background of an ImageView

Get the Drawable from imageView using getBackground():

Drawable background = imageView.getBackground();

Check against usual suspects:

if (background instanceof ShapeDrawable) {
    // cast to 'ShapeDrawable'
    ShapeDrawable shapeDrawable = (ShapeDrawable) background;
    shapeDrawable.getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    // cast to 'GradientDrawable'
    GradientDrawable gradientDrawable = (GradientDrawable) background;
    gradientDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    // alpha value may need to be set again after this call
    ColorDrawable colorDrawable = (ColorDrawable) background;
    colorDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

Compact version:

Drawable background = imageView.getBackground();
if (background instanceof ShapeDrawable) {
    ((ShapeDrawable)background).getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    ((GradientDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    ((ColorDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

Note that null-checking is not required.

However, you should use mutate() on the drawables before modifying them if they are used elsewhere. (By default, drawables loaded from XML share the same state.)

Solution 2:[2]

A simpler solution nowadays would be to use your shape as a background and then programmatically change its color via:

view.background.setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP)

See PorterDuff.Mode for the available options.

UPDATE (API 29):

The above method is deprecated since API 29 and replaced by the following:

view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)

See BlendMode for the available options.

Solution 3:[3]

Do like this:

    ImageView imgIcon = findViewById(R.id.imgIcon);
    GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
    backgroundGradient.setColor(getResources().getColor(R.color.yellow));

Solution 4:[4]

This question was answered a while back, but it can modernized by rewriting as a kotlin extension function.

fun Drawable.overrideColor(@ColorInt colorInt: Int) {
    when (this) {
        is GradientDrawable -> setColor(colorInt)
        is ShapeDrawable -> paint.color = colorInt
        is ColorDrawable -> color = colorInt
    }
}

Solution 5:[5]

Try this:

 public void setGradientColors(int bottomColor, int topColor) {
 GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]  
 {bottomColor, topColor});
 gradient.setShape(GradientDrawable.RECTANGLE);
 gradient.setCornerRadius(10.f);
 this.setBackgroundDrawable(gradient);
 }

for more detail check this link this

hope help.

Solution 6:[6]

hope this will help someone with the same issue

GradientDrawable gd = (GradientDrawable) YourImageView.getBackground();
//To shange the solid color
gd.setColor(yourColor)

//To change the stroke color
int width_px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, youStrokeWidth, getResources().getDisplayMetrics());
gd.setStroke(width_px, yourColor);

Solution 7:[7]

Expanding on Vikram's answer, if you are coloring dynamic views, like recycler view items, etc.... Then you probably want to call mutate() before you set the color. If you don't do this, any views that have a common drawable (i.e a background) will also have their drawable changed/colored.

public static void setBackgroundColorAndRetainShape(final int color, final Drawable background) {

    if (background instanceof ShapeDrawable) {
        ((ShapeDrawable) background.mutate()).getPaint().setColor(color);
    } else if (background instanceof GradientDrawable) {
        ((GradientDrawable) background.mutate()).setColor(color);
    } else if (background instanceof ColorDrawable) {
        ((ColorDrawable) background.mutate()).setColor(color);
    }else{
        Log.w(TAG,"Not a valid background type");
    }

}

Solution 8:[8]

this is the solution that works for me...wrote it in another question as well: How to change shape color dynamically?

//get the image button by id
ImageButton myImg = (ImageButton) findViewById(R.id.some_id);

//get drawable from image button
GradientDrawable drawable = (GradientDrawable) myImg.getDrawable();

//set color as integer
//can use Color.parseColor(color) if color is a string
drawable.setColor(color)

Solution 9:[9]

Nothing work for me but when i set tint color it works on Shape Drawable

 Drawable background = imageView.getBackground();
 background.setTint(getRandomColor())

require android 5.0 API 21

Solution 10:[10]

My Kotlin extension function version based on answers above with Compat:

fun Drawable.overrideColor_Ext(context: Context, colorInt: Int) {
    val muted = this.mutate()
    when (muted) {
        is GradientDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        is ShapeDrawable -> muted.paint.setColor(ContextCompat.getColor(context, colorInt))
        is ColorDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        else -> Log.d("Tag", "Not a valid background type")
    }
}

Solution 11:[11]

The simple way to fill the shape with the Radius is:

(view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);

Solution 12:[12]

May be I am too late.But if you are using Kotlin. There is way like this

var gd = layoutMain.background as GradientDrawable

 //gd.setCornerRadius(10)
  gd.setColor(ContextCompat.getColor(ctx , R.color.lightblue))
  gd.setStroke(1, ContextCompat.getColor(ctx , R.color.colorPrimary)) // (Strokewidth,colorId)

Enjoy....

Solution 13:[13]

For anyone using C# Xamarin, here is a method based on Vikram's snippet:

private void SetDrawableColor(Drawable drawable, Android.Graphics.Color color)
{
    switch (drawable)
    {
        case ShapeDrawable sd:
            sd.Paint.Color = color;
            break;
        case GradientDrawable gd:
            gd.SetColor(color);
            break;
        case ColorDrawable cd:
            cd.Color = color;
            break;
    }
}

Solution 14:[14]

The Best way to change Solid color of custom drawable is For Kotlin.

 (findViewById<TextView>(R.id.testing1).getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN); 

Solution 15:[15]

This might help

1.Set the shape color initially to transparent

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
   <solid android:angle="270"
       android:color="@android:color/transparent"/>
   <stroke android:width="3dp"
        android:color="#FFAA0055"/>
</shape>
  1. Set the shape as a background to the view

  2. Set your preferred color as follows:

    Drawable bg = view.getBackground();
    bg.setColorFilter(Color.parseColor("#Color"), PorterDuff.Mode.ADD);
    

Solution 16:[16]

I needed to do this in my adapter but the solutions above were either not working or required >= android version 10. The code below worked for me!

val drawable = DrawableCompat.wrap(holder.courseName.background)
DrawableCompat.setTint(drawable, Color.parseColor("#4a1f60"))