1

I've tried to create some kind of custom rounded button like in this answer. But I need many of them (about 18) for my GridView, and all of them should have different background color.

Unfortunately, view.setBackgroundColor(int c) not only changes the color of my custom button, but it changes the shape to (so my rounded corners just disapear.

So, is there any way to just change the background color of the view (color of the shape) and not changing it's shape? (Creating 18 different xmls isn't the best way)

Full code of addapter:

PaletteView view = (PaletteView) ((convertView == null) ? mInflater.inflate(R.layout.palette_item, null)
            : convertView);

    view.findViewById(R.id.rounded).setBackgroundColor(mColors[position]);

    return view;
Community
  • 1
  • 1
Paul Freez
  • 1,059
  • 15
  • 27
  • Please check [this](http://stackoverflow.com/questions/9334618/rounded-button-android?lq=1) and [this](http://stackoverflow.com/questions/6054562/how-to-make-the-corners-of-a-button-round?lq=1) may help you – swiftBoy Jul 02 '14 at 10:05
  • @RDC you provided the links on how to _create_ rounded buttons. I got a little bit different problem as you can see. – Paul Freez Jul 02 '14 at 10:23
  • The second link include info about background color also, that's why i shared with you. – swiftBoy Jul 02 '14 at 10:25
  • @RDC Yes, but it's hardcoded and tied to specific shape. If I'll do this in my case - I'll need to create 18 similar shapes with different colors. I don't think that's rational – Paul Freez Jul 02 '14 at 10:29

2 Answers2

0

No time to test but maybe...

Add an ID (shape_id) to the item you wish to change colour to in your drawable. Then use the following

 LayerDrawable bgDrawable = (LayerDrawable) view.getBackground();
 GradientDrawable shape = (GradientDrawable) bgDrawable.findDrawableByLayerId(R.id.shape_id);
 shape.setColor(mColors[position]);

https://stackoverflow.com/a/16637696/3309883

Community
  • 1
  • 1
Unknownweirdo
  • 485
  • 6
  • 16
  • No, this code rises classcast exception: android.graphics.drawable.StateListDrawable cannot be cast to android.graphics.drawable.LayerDrawable I think that's because I'm using selector (with 2 states-items focused and unfocused) for my custom button. – Paul Freez Jul 02 '14 at 10:20
0

So, I've found the way to resolve it - create shapes/selector programmaticaly.

Now, I only got rounded_shape.xml with just a shape:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >

<corners android:radius="@dimen/rounded_radius" />

<stroke android:width="1dip" />

And created static class for creating full selectors for the button:

public class DrawableUtils {

/**
 * Blend {@code color1} and {@code color2} using the given ratio.
 * 
 * @param ratio
 *            of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, 0.0 will return
 *            {@code color2}.
 */
private static int blendColors(int color1, int color2, float ratio) {
    final float inverseRation = 1f - ratio;
    float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
    float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
    float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
    return Color.rgb((int) r, (int) g, (int) b);
}

/**
 * Create selector with specified {@code mainColor} (setting darkened {@code mainColor} for state_pressed)
 * 
 * @param mainColor
 *            color of the view
 */
public static StateListDrawable getSelector(Context c, int mainColor) {
    StateListDrawable selector = new StateListDrawable();
    /*
     * CAREFUL! We NEED to use 2 different objects instead of using 1 with different setColor(...) calls
     */
    GradientDrawable stateSimple, statePressed;

    // Getting pre-created shape
    statePressed = (GradientDrawable) c.getResources().getDrawable(R.drawable.rounded_shape);
    stateSimple = (GradientDrawable) c.getResources().getDrawable(R.drawable.rounded_shape);

    // Setting color for state_pressed
    statePressed.setColor(blendColors(mainColor, c.getResources().getColor(R.color.tinted_black), 0.5f));
    selector.addState(new int[] { android.R.attr.state_pressed }, statePressed);
    selector.addState(new int[] { -android.R.attr.state_enabled }, statePressed);   // "-" is for "false"

    // Setting color for main state
    stateSimple.setColor(mainColor);
    selector.addState(new int[] { android.R.attr.state_enabled }, stateSimple);

    return selector;
}

}

Finaly, calling this from the GridView adapter:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        view.findViewById(R.id.rounded).setBackgroundDrawable(DrawableUtils.getSelector(mC, mColors[position]));
    } else {
        view.findViewById(R.id.rounded).setBackground(DrawableUtils.getSelector(mC, mColors[position]));
    }
Paul Freez
  • 1,059
  • 15
  • 27