Reputation: 13985
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
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
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
Reputation: 11
GradientDrawable gd = new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
new int[] {0xFF616261,0xFF131313});
gd.setCornerRadius(0f);
layout.setBackgroundDrawable(gd);
Upvotes: 0
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
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>
Set the shape as a background to the view
Set your preferred color as follows:
Drawable bg = view.getBackground();
bg.setColorFilter(Color.parseColor("#Color"), PorterDuff.Mode.ADD);
Upvotes: 1
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
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
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
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
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
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
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
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
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
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
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
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
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
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