Palette colour overrides Outline - android

I'm making an app just to check out some of the new L APIs, and I'm particularly interested in the FloatingActionButton and the Palette colour generator. So I set a full screen ImageView to display an HTC wallpaper, I then extract one of the colours with Palette and set it as the background colour of my FAB. However, doing this removes the Outline from my FAB, so it's no longer circular.
I would like to know how, if possible, to stop the Palette overriding the Outline.
The Palette AsyncListener:
MyActivity.java
Palette.generateAsync(BitmapFactory.decodeResource(getResources(),R.drawable.wallpapers_07),
new Palette.PaletteAsyncListener() {
#Override
public void onGenerated(Palette palette) {
PaletteItem item = palette.getLightVibrantColor();
ImageButton button = (ImageButton) findViewById(R.id.fab);
if (item != null) {
button.setBackgroundColor(item.getRgb());
}
}
});
Outline in MyActivity.java
int size = getResources().getDimensionPixelSize(R.dimen.fab_size);
Outline outline = new Outline();
outline.setOval(0, 0, size, size);
findViewById(R.id.fab).setOutline(outline);
FAB background drawable
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item>
<shape android:shape="oval">
<solid android:color="?android:colorAccent"/>
</shape>
</item>

You are replacing the background drawable (RippleDrawable) with a color (ColorDrawable). Instead, you want to change the color of the shape (GradientDrawable) contained with the background drawable.
Try changing the color filter instead:
findViewById(R.id.fab).getBackgroundDrawable().setColorFilter(
new PorterDuffColorFilter(item.getRgb(), Mode.SRC_IN));
If you're changing the color often, you can just cache the color filter object and use setColor(int) followed by findViewById(R.id.fab).invalidate() to update the view.

Related

Android change drawable solid color programmatically

I have a drawable that is an oval shape with a with check mark inside.
Is it possible to change the oval color programmatically without changing the check mark color ?
Here's my drawable:
<item>
<shape
android:shape="oval">
<solid android:color="#color/black" />
</shape>
</item>
<item>
<bitmap
android:src="#drawable/check_mark"/>
</item>
What I would like to do is only change the solid black color to something else programmatically
It would be easier to just add a second drawables with other "oval"-color and then replace the drawable programmatically.
You can grammatically create a shape using below reference code.
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius(24);
shape.setShape(GradientDrawable.OVAL);
shape.setColor(R.color.red);
imageView.setBackground(shape);
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));
}

CustomSeekBar with fading alpha color gradient, black thin border, and tiled background

The goal
I'm trying to replicate this Dialog.
The current state
But I've only gotten to this point (showing only the relevant part):
What is missing
A way to add a thin black border surrounding my custom Seekbar's "progress area", and a tiled background restricted to that "progress area".
My code
As it is, my CustomSeekBar (which extends AppCompatSeekBar) works fine for setting a starting and ending color in the code. Here is the function:
public void setGradientColor(#ColorInt int leftColor, #ColorInt int rightcolor) {
grad = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT,
new int[] {leftColor, rightcolor});
setProgressDrawable(grad);
}
But trying to set the background's image ends up looking like my very last seekbar in the The current state image (the background extends outside of the progress area and fills all of the view's area):
aSeekBar.setBackground(context.getDrawable(R.drawable.checker));
aSeekBar.setGradientColor(Color.parseColor("#00000000"), Color.parseColor("#FF000000"));
My checker.xml file in res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/checkerstile"
android:tileMode="repeat"
/>
For the "Border" part of your question, you just have to add a Stroke to your GradientDrawable :
public void setGradientColor(#ColorInt int leftColor, #ColorInt int rightcolor) {
grad = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT,
new int[] {leftColor, rightcolor});
grad.setStroke(/* stroke width*/, /* int color*/);
setProgressDrawable(grad);
}
For that, it that easy, sorry i can't help for the background.
I've found a viable solution:
int padding = aSeekBar.getPaddingStart();
InsetDrawable bgImg = new InsetDrawable(context.getDrawable(R.drawable.checker), padding);
aSeekBar.setBackground(bgImg);
Combine this with the solution from Olivier for the border and you get this result:

How to change drawable of specific Star in RatingBar?

I want to create ratingBar like penalty bar in Football
i created my custom RatingBar by this style:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#android:id/background"
android:drawable="#drawable/circle_grey"/>
<item
android:id="#android:id/secondaryProgress"
android:drawable="#drawable/circle_green"/>
<item
android:id="#android:id/progress"
android:drawable="#drawable/circle_red"/>
More explain:
when user got a goal so change the star drawable by index 2 in ratingBar and if user unsuccessful change star drawabale by index 2 in ratingBar to red drawable.
red drawable
green drawable
gray drawable
my RatingBar
That's what I want
How to do it?
Since you want to change the color of the rating bar based on the condition, you have to do it programatically by changing your layer-list.
say if the player has made a goal.
private static int GREEN = 0; // progress
private static int RED= 1; // secondary progress
private static int YELLOW= 2; // background
RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(GREEN).setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(RED).setColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(YELLOW).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);
if player hasn't made goal then,
RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(GREEN).setColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(RED).setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(YELLOW).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);
Note: Make sure you have made the order i have in the layer-list.

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?
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.
Do like this:
ImageView imgIcon = findViewById(R.id.imgIcon);
GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
backgroundGradient.setColor(getResources().getColor(R.color.yellow));
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
}
}
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);
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");
}
}
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)
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
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")
}
}
The simple way to fill the shape with the Radius is:
(view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);
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....
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);
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"))
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;
}
}
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);
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")
GradientDrawable gd = new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
new int[] {0xFF616261,0xFF131313});
gd.setCornerRadius(0f);
layout.setBackgroundDrawable(gd);

How to easily change the color of a progressBar in Android?

I would like to dynamically update the ProgressBar Color, in order to match with the layout of the application that changes in realtime.
The idea is to change the color according to the value set.
I found some solution but seems heavy to have that running in an animation updating several times per second.
Use ProgressBar's method:
public void setProgressDrawable (Drawable d)
and pass Drawable in different colors, ex. ColorDrawable which has setColor(int color) method.
To change png drawable colors on the fly try: How to change colors of a Drawable in Android?
EDIT:
ProgressBar drawable is LayerDrawable that looks like:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:drawable/screen_progress_frame" />
<item>
<scale scaleWidth="100%" scaleGravity="0x3" drawable="#android:drawable/screen_progress_inner" />
</item>
</layer-list>
It has ScaleDrawable which you want to colorize.
Create your own LayerDrawable similar to the above and extract bar drawable and change color of it.
This is solution which you can use in code (based on the solution of pawelzieba).
ProgressBar progressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal);
progressBar.setProgressDrawable(new LayerDrawable(
new Drawable[] {
new ColorDrawable(Color.RED),
new ScaleDrawable(new ColorDrawable(Color.GREEN), Gravity.LEFT, 1, -1),
}));
...
progressBar.setProgress(20);
Well, for anyone looking for how to do it programmatically: do not forget to set ids to your Drawables!
Drawable bckgrndDr = new ColorDrawable(Color.RED);
Drawable secProgressDr = new ColorDrawable(Color.GRAY);
Drawable progressDr = new ScaleDrawable(new ColorDrawable(Color.BLUE), Gravity.LEFT, 1, -1);
LayerDrawable resultDr = new LayerDrawable(new Drawable[] { bckgrndDr, secProgressDr, progressDr });
//setting ids is important
resultDr.setId(0, android.R.id.background);
resultDr.setId(1, android.R.id.secondaryProgress);
resultDr.setId(2, android.R.id.progress);
Setting ids to drawables is crucial, and takes care of preserving bounds and actual state of progress bar.
(It seeems that solution proposed by vmayatskii sort of works - but only if you call setProgress(value) aftrawards, and this value has to be different from current progress value)

Categories

Resources