Change Button Color programmatically - android

I have some Buttons in my App at different places. I want to color them according to the location they are in. (Blue Button in Fragment1, Red Button in Fragment2)
I already tried ColorFilter, but that doesn't work with API < 21. I know it is possible to create xml for that, but I don't want to create one for every section in my App. Is it possible to create somehow Backgroud Drawables, which have the color I specify and have the Button animations? (Ripple and selector for API < 21)

I found the solution:
**
* Sets the color of a button.
* #param button The Button which should be colored.
* #param color The color as a already retrieved value.
*/
public static void setButtonColor(Button button, int color) {
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
//calculate darker color
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f;
int darkColor = Color.HSVToColor(hsv);
StateListDrawable listDrawable = new StateListDrawable();
GradientDrawable standard = new GradientDrawable();
GradientDrawable pressed = new GradientDrawable();
standard.setColor(color);
standard.setCornerRadius(3);
pressed.setColor(darkColor);
pressed.setCornerRadius(3);
listDrawable.addState(new int[]{android.R.attr.state_pressed}, pressed);
listDrawable.addState(new int[]{android.R.attr.state_focused}, pressed);
listDrawable.addState(StateSet.WILD_CARD, standard);
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
//noinspection deprecation
button.setBackgroundDrawable(listDrawable);
} else {
button.setBackground(listDrawable);
}
} else {
button.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}
}
I don't know if this is the best selection, but it works.

Related

Show Dynamic colors on recyclerview list numberings

I want to achieve something like this:
See the image here
A list with circular shape drawable with a fill of a light variant color of the image tint color
I have tried textrdrawablelibrary but it does not give me the same. I have tried the following code too but to no avail:
public int darkenColor(int color) {
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // value component
color = Color.HSVToColor(hsv);
return color;
}
public String[] mColors = {
"5E97F6",
"9CCC65",
"FF8A65",
"9E9E9E",
"9FA8DA",
"90A4AE",
"AED581",
"F6BF26",
"FFA726",
"4DD0E1",
"BA68C8",
"A1887F",
};
// all colors used by gmail application :)
light colors
// genrating random num from 0 to 11 because you can add more or less
int i1 = new Random().nextInt(11);
//genrating shape with colors
GradientDrawable draw = new GradientDrawable();
draw.setShape(GradientDrawable.OVAL);
draw.setColor(Color.parseColor ("#"+mColors[i1]));
// assigning to textview
contact_name_circle.setBackground(draw); //textview

Progress bar with round corners and multiple colors

I've read already similar questions here and here and are good solutions if you only want to show a single progress bar with rounded corners, but in my case I want to show a progress made out of multiple "sub-progress" colors like in the image below:
What I've done so far is to code a LinearGradient implementation like this answer but it looks squared in the corners.
How can I obtain this progress?
After some research I found this class PaintDrawable which I can set as background of any View, and surprisingly I can set a Shape to this Drawable, so if I use the RoudRectShape it seems rounded as I want it to be, my final code is as follows:
// mRatios is a View
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
#Override
public Shader resize(int i, int i1) {
LinearGradient lg = new LinearGradient(0, 0, mRatios.getWidth(), 0,
barColorsArray,
barRatiosArray,
Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable paintDrawable = new PaintDrawable();
// not sure how to calculate the values here, but it works with these constants in my case
paintDrawable.setShape(new RoundRectShape(new float[]{100,100,100,100,100,100,100,100}, null, null));
paintDrawable.setShaderFactory(sf);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mRatios.setBackgroundDrawable(paintDrawable);
} else {
mRatios.setBackground(paintDrawable);
}

mixing two gradient drawable for a view in android

I am trying to draw some colors in the background of a view.
The colors are to be placed as linear gradients and in different directions.
So i did the following:
private Orientation[] orientations = new Orientation[]{Orientation.BL_TR, Orientation.BR_TL, Orientation.TL_BR, Orientation.TR_BL, Orientation.TOP_BOTTOM};
public void drawBackgroudGradient(RelativeLayout backgroundView, int[] colors){
if (colors != null){
if (colors.length > 1){
for (int i=0; i<colors.length; i++){
backgroundView.setBackgroundDrawable(getGradientDrawable(colors[i], orientations[i]));
}
}else{
//in case of only one color just set that color as background
backgroundView.setBackgroundColor(colors[0]);
}
}
}
private GradientDrawable getGradientDrawable(int color, Orientation orientation){
int[] colors = new int[] {color, Color.WHITE};
GradientDrawable drawable = new GradientDrawable(orientation, colors);
drawable.setAlpha(125);
return drawable;
}
I have each drawable going from the starting color to transparent so that all the gradients are visible.
But the problem is that all the colors are not showing up. Only the last color is drawn via the gradient drawable. the rest can not be seen.
Could someone please help me figure out how to mix and show all the colors?
Thanks.
Sunny
create LayerDrawable and mix them:
private LayerDrawable getGradientDrawable(int color, Orientation orientation){
int[] colors = new int[] {color, Color.WHITE};
GradientDrawable drawable1 = new GradientDrawable(orientation, colors);
drawable1.setAlpha(125);
GradientDrawable drawable2 = new GradientDrawable();
drawable2.setStroke(4, Color.parseColor("#FFFFFF"));
drawable2.setColor(Color.TRANSPARENT);
return new LayerDrawable(new Drawable[]{drawable1 , drawable2});
}
drawable2 placed on top of drawable1.

Get the background color of a button in android

How do i get the background color of a button.
In the xml i set the background color using ---- android:background = XXXXX
now in the activity class how can i retrieve this value that it has ?
Unfortunately I don't know how to retrieve the actual color.
It's easy to get this as a Drawable
Button button = (Button) findViewById(R.id.my_button);
Drawable buttonBackground = button.getBackground();
If you know this is a color then you can try
ColorDrawable buttonColor = (ColorDrawable) button.getBackground();
And if you're on Android 3.0+ you can get out the resource id of the color.
int colorId = buttonColor.getColor();
And compare this to your assigned colors, ie.
if (colorID == R.color.green) {
log("color is green");
}
private Bitmap mBitmap;
private Canvas mCanvas;
private Rect mBounds;
public void initIfNeeded() {
if(mBitmap == null) {
mBitmap = Bitmap.createBitmap(1,1, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBounds = new Rect();
}
}
public int getBackgroundColor(View view) {
// The actual color, not the id.
int color = Color.BLACK;
if(view.getBackground() instanceof ColorDrawable) {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
initIfNeeded();
// If the ColorDrawable makes use of its bounds in the draw method,
// we may not be able to get the color we want. This is not the usual
// case before Ice Cream Sandwich (4.0.1 r1).
// Yet, we change the bounds temporarily, just to be sure that we are
// successful.
ColorDrawable colorDrawable = (ColorDrawable)view.getBackground();
mBounds.set(colorDrawable.getBounds()); // Save the original bounds.
colorDrawable.setBounds(0, 0, 1, 1); // Change the bounds.
colorDrawable.draw(mCanvas);
color = mBitmap.getPixel(0, 0);
colorDrawable.setBounds(mBounds); // Restore the original bounds.
}
else {
color = ((ColorDrawable)view.getBackground()).getColor();
}
}
return color;
}
You can also try something like set the color value as the tag like
android:tag="#ff0000"
And access it from the code
String colorCode = (String)btn.getTag();
The simpliest way to get the color for me is:
int color = ((ColorDrawable)button.getBackground()).getColor();
Tested and working on Lollipop 5.1.1
To get the background Drawable, you use
public Drawable getBackground();
as defined in the base View class.
Don't forget that the Button can have a background that is an image, a color, a gradient. If you use android:background="#ffffff", the class of the background will be
android.graphics.drawable.ColorDrawable
From there you can simply call
public int getColor()
Try this:
list_view.getChildAt(position).setBackgroundColor(Color.YELLOW);
ColorDrawable corItem = (ColorDrawable) list_view.getChildAt(position).getBackground();
if(corItem.getColor() == Color.YELLOW){
Toast.makeText(NovoProcessoActivity.this,"Right Color!", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(NovoProcessoActivity.this,"Wrong Color!", Toast.LENGTH_SHORT).show();
}
or
int color =( (ColorDrawable) list_view.getChildAt(position).getBackground()).getColor();
int colornumber=((ColorDrawable)v.getBackground()).getColor();
This is the best and simple way to get the color of a View (Button, TextView...)
To get set color to a View using java we use
v.setBackgroundColor(getColor(R.color.colorname_you_used));

Android: How to create a StateListDrawable programmatically

I have a GridView to display some objects, and visually each of the objects will have an image icon and a text label. I also want the image icon to have some "push and pop" effect when clicked, that is, when pressed, the image will move a small distance to the bottom right direction, and when released get back to its original position.
The objects (and their image icons) are from some dynamic sources. My intuition is to create a StateListDrawable for each item, which will have two states: pressed or not. For GridView item view, I would use a Button, which can accomodate a Drawable and a label, that perfectly satisfies my requirment.
I defined an item class to wrap up the original object:
public class GridItem<T> {
public static final int ICON_OFFSET = 4;
private StateListDrawable mIcon;
private String mLabel;
private T mObject;
public Drawable getIcon() {
return mIcon;
}
public void setIcon(Drawable d) {
if (null == d) {
mIcon = null;
}else if(d instanceof StateListDrawable) {
mIcon = (StateListDrawable) d;
} else {
InsetDrawable d1 = new InsetDrawable(d, 0, 0, ICON_OFFSET, ICON_OFFSET);
InsetDrawable d2 = new InsetDrawable(d, ICON_OFFSET, ICON_OFFSET, 0, 0);
mIcon = new StateListDrawable();
mIcon.addState(new int[] { android.R.attr.state_pressed }, d2);
mIcon.addState(StateSet.WILD_CARD, d1);
//This won't help either: mIcon.addState(new int[]{}, d1);
}
}
public String getLabel() {
return mLabel;
}
public void setLabel(String l) {
mLabel = l;
}
public T getObject() {
return mObject;
}
public void setObject(T o) {
mObject = o;
}
}
Now the problem is, when I touch a grid item, the icon "moves" quite as I have expected, but it won't restore its original position when my finger lifts up leaving the item.
My question is: how to programmatically create a StateListDrawable equivalent to one inflated from an XML resource like
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/image_pressed" />
<item android:drawable="#drawable/image_normal" />
</selector>
?
if your drawables are just bitmaps, you could draw them programmatically, for now it should help, however I wonder what is the problem with InsetDrawable usage here, basically use prepared BitmapDrawables that are drawn programatically, you would need to modify your method to accept bitmaps b
Bitmap bc1 = Bitmap.createBitmap(b.getWidth() + ICON_OFFSET, b.getHeight() + ICON_OFFSET, Bitmap.Config.ARGB_8888);
Canvas c1 = new Canvas(bc1);
c1.drawBitmap(b, 0, 0, null);
Bitmap bc2 = Bitmap.createBitmap(b.getWidth() + ICON_OFFSET, b.getHeight() + ICON_OFFSET, Bitmap.Config.ARGB_8888);
Canvas c2 = new Canvas(bc2);
c2.drawBitmap(b, ICON_OFFSET, ICON_OFFSET, null);
mIcon = new StateListDrawable();
mIcon.addState(new int[] { android.R.attr.state_pressed }, new BitmapDrawable(bc2));
mIcon.addState(StateSet.WILD_CARD, new BitmapDrawable(bc1));
I can see the answer is already accepted. I am sharing if you want to assign dynamically colors of buttons from the users for normal as well as pressed state. then you can just call this function :
public static StateListDrawable convertColorIntoBitmap(String pressedColor, String normalColor){
/*Creating bitmap for color which will be used at pressed state*/
Rect rectPressed = new Rect(0, 0, 1, 1);
Bitmap imagePressed = Bitmap.createBitmap(rectPressed.width(), rectPressed.height(), Config.ARGB_8888);
Canvas canvas = new Canvas(imagePressed);
int colorPressed = Color.parseColor(pressedColor);
Paint paintPressed = new Paint();
paintPressed.setColor(colorPressed);
canvas.drawRect(rectPressed, paintPressed);
RectF bounds = new RectF();
bounds.round(rectPressed);
/*Creating bitmap for color which will be used at normal state*/
Rect rectNormal = new Rect(0, 0, 1, 1);
Bitmap imageNormal = Bitmap.createBitmap(rectNormal.width(), rectNormal.height(), Config.ARGB_8888);
Canvas canvasNormal = new Canvas(imageNormal);
int colorNormal = Color.parseColor(normalColor);
Paint paintNormal = new Paint();
paintNormal.setColor(colorNormal);
canvasNormal.drawRect(rectNormal, paintNormal);
/*Now assigning states to StateListDrawable*/
StateListDrawable stateListDrawable= new StateListDrawable();
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new BitmapDrawable(imagePressed));
stateListDrawable.addState(StateSet.WILD_CARD, new BitmapDrawable(imageNormal));
return stateListDrawable;
}
Now all you need is to set it as your textview or button background like below :
if(android.os.Build.VERSION.SDK_INT>=16){
yourbutton.setBackground(convertColorIntoBitmap("#CEF6CE00","#4C9D32"));
}else{
yourbutton.setBackgroundDrawable(convertColorIntoBitmap("#CEF6CE00","#4C9D32"));
}
Here you can see all you need to pass the colors dynamically and we're done. hope this will help someone :) You can find it's gist too here :)
I have seen the previous answers, but came up with a much shorter and better solution using ColorDrawable.
/**
* Get {#link StateListDrawable} given the {#code normalColor} and {#code pressedColor}
* for dynamic button coloring
*
* #param normalColor The color in normal state.
* #param pressedColor The color in pressed state.
* #return
*/
public static StateListDrawable getStateListDrawable(int normalColor, int pressedColor) {
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(pressedColor));
stateListDrawable.addState(StateSet.WILD_CARD, new ColorDrawable(normalColor));
return stateListDrawable;
}
This accepts resolved colors as integer and uses ColorDrawable to add them in a StateListDrawable.
Once you have the drawable, you can use it simply like this,
if (android.os.Build.VERSION.SDK_INT >= 16) {
mButton.setBackground(Utils.getStateListDrawable(ResourceUtils.getColor(R.color.white),
ResourceUtils.getColor(R.color.pomegranate)));
} else {
mButton.setBackgroundDrawable(Utils.getStateListDrawable(ResourceUtils.getColor(R.color.white),
ResourceUtils.getColor(R.color.pomegranate)));
}

Categories

Resources