Cote Mounyo
Cote Mounyo

Reputation: 13985

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?

Upvotes: 232

Views: 173409

Answers (19)

Christophy Barth
Christophy Barth

Reputation: 487

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"))

EDIT!!: OR if your color is an Int and not a Hex

val myDrawable = DrawableCompat.wrap(holder.courseName.background)
DrawableCompat.setTint(myDrawable, ContextCompat.getColor(context, newColor))

ADDED INFO!!: Another way to do this is to get the drawable, change its tint first, then set it to the background of your view.

val tintDrawable = ContextCompat.getDrawable(context, R.drawable.my_shape)!!.mutate()
DrawableCompat.setTint(tintDrawable, ContextCompat.getColor(context, newColor))
view.background = tintDrawable

Upvotes: 1

Rafa J
Rafa J

Reputation: 61

For 2023 with compileSdkVersion 33 the most voted answer at this moment worked in some way. My shape it's a simple rounded border for a complex view.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <stroke
        android:width="2dp"
        android:color="@color/white"/>
    <corners
        android:bottomRightRadius="10dp"
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp"
        android:bottomLeftRadius="10dp"/>
</shape>

The shape is set as background in a view with name VScroll. I need the color of the shape to be the same as the themed view so I adapted the accepted answer and set the color in the Fragment:

val lineBackground = binding.vScroll.background as GradientDrawable
lineBackground.setStroke(5,Color.parseColor(line.color))

Where line.color is an hexadecimal string value like #FFFFFF. The int value for the stroke width is set in pixels, so it has to be converted to dp for a correct size.

Upvotes: 0

ABU Ali14Q
ABU Ali14Q

Reputation: 11

GradientDrawable gd = new GradientDrawable(
        GradientDrawable.Orientation.TOP_BOTTOM,
        new int[] {0xFF616261,0xFF131313});
gd.setCornerRadius(0f);

layout.setBackgroundDrawable(gd);

Upvotes: 0

Rumit Patel
Rumit Patel

Reputation: 12629

We can create this kotlin function.

fun View.updateViewBGSolidColor(colorString: String) {
    when (val background: Drawable = this.background) {
        is ShapeDrawable -> {
            background.paint.color = Color.parseColor(colorString)
        }
        is GradientDrawable -> {
            background.setColor(Color.parseColor(colorString))
        }
        is ColorDrawable -> {
            background.color = Color.parseColor(colorString)
        }
    }
}

And use it like the below:

yourTextView.updateViewBGSolidColor("#FFFFFF")

Upvotes: 0

afhamu
afhamu

Reputation: 1029

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);
    

Upvotes: 1

Asif Ashraf
Asif Ashraf

Reputation: 11

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); 

Upvotes: 0

Georgios
Georgios

Reputation: 5097

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.

Upvotes: 79

Zealous System
Zealous System

Reputation: 2324

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....

Upvotes: 1

Ryan
Ryan

Reputation: 2065

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;
    }
}

Upvotes: 1

Sattar Hummatli
Sattar Hummatli

Reputation: 1408

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")
    }
}

Upvotes: 3

Sumit
Sumit

Reputation: 1122

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

Upvotes: 7

SANAT
SANAT

Reputation: 9287

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

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

Upvotes: 2

Carlos Paulino
Carlos Paulino

Reputation: 796

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
    }
}

Upvotes: 26

Vikram
Vikram

Reputation: 51581

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.)

Upvotes: 310

Tyler Pfaff
Tyler Pfaff

Reputation: 5052

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");
    }

}

Upvotes: 12

user1750873
user1750873

Reputation:

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)

Upvotes: 7

medhdj
medhdj

Reputation: 1178

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);

Upvotes: 15

Leonly91
Leonly91

Reputation: 613

Do like this:

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

Upvotes: 51

androidqq6
androidqq6

Reputation: 1526

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.

Upvotes: 16

Related Questions