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?
This question is related to
android
android-layout
shape
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
}
}
Do like this:
ImageView imgIcon = findViewById(R.id.imgIcon);
GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
backgroundGradient.setColor(getResources().getColor(R.color.yellow));
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.)
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.
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....
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;
}
}
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.
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);
The simple way to fill the shape with the Radius is:
(view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);
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)
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");
}
}
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")
}
}
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
Source: Stackoverflow.com