Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
284 views
in Technique[技术] by (71.8m points)

android - Change the shape color of a ImageButton

I have a recyclerView where I create 12 ImageButtons. As default they are all black colored, because I made a custom shape for the imageButton that have a black solid color. The custom shape is set as the imageButtons background

The shape:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners
    android:radius="5.3dp"/>
<solid
    android:color="#000000"/>


</shape>

This is how the ImageButtons look like now. But they all have the same color, which is not what I want.

enter image description here

I want dynamically to give each ImageButton a different color from my color-array in my color.xml. I have tried many of the solution of how to change the solid color of a shapes but none of them have worked.

Method that creates 12 imageButton for the recyclerView:

 public static List<ColorButton> initColorButtons(){

    colorButtonList = new ArrayList<>();

    //here we retrive all colors from color.xml
    Resources resources = App.getAppContext().getResources();
    String colors[] = resources.getStringArray(R.array.backgroundcolors);

        for(int i=0; i<colors.length; i++){

        //Creates 12 ImageButtons with a custom shape
        colorButtonList.add(new ColorButton(new ImageButton(App.getAppContext()), colors[i]));


        //Here each imagebutton should get its own color.
        Drawable drawable = colorButtonList.get(i).getButton().getBackground();

        if (colorButtonList.get(i).getButton().getBackground() instanceof GradientDrawable) {

            GradientDrawable gd = (GradientDrawable) drawable.getCurrent();
            gd.setColor(Color.parseColor(colors[i]));

    }
}
    return colorButtonList;
}

The Imagebutton that is created for the recyclerView. The @drawable/bbtn shapes backgrundcolor is set to black as default

<?xml version="1.0" encoding="utf-8"?>
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/colorbutton"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="7dp"
android:layout_marginTop="25dp"
android:layout_marginBottom="25dp"
android:background="@drawable/bbtn">

</ImageButton>

Here are the color-array. Each button should have a different background color of one of the list:

  <string-array name="backgroundcolors">
    <item>#000000</item>
    <item>#ffffff</item>
    <item>#373737</item>
    <item>#e6e6e6</item>
    <item>#EAE1D8</item>
    <item>#fd79a1</item>
    <item>#E849A1</item>
    <item>#ff0f68</item>
    <item>#c22032</item>
    <item>#F7E84E</item>
    <item>#0d4b7e</item>
    <item>#329de7</item>
    <item>#68be3f</item>
    <item>#006c35</item>
    <item>#395a4f</item>
    </string-array>

This is the class where I create ImageButtons

public class ColorButton{

private ImageButton button;
private String color;
public static List<ColorButton> colorButtonList;


public ColorButton(ImageButton button, String color) {
    this.button = button;
    this.color = color;
}

public String getColor() {
    return color;
}

public void setColor(String color) {
    this.color = color;
}

public ImageButton getButton() {
    return button;
}

@SuppressLint("NewApi")
public static List<ColorButton> initColorButtons(){
    colorButtonList = new ArrayList<>();

    //here we retrive all colors from color.xml
    Resources resources = App.getAppContext().getResources();
    String colors[] = resources.getStringArray(R.array.backgroundcolors);

    for(int i=0; i<colors.length; i++){
        //Creates 12 ImageButtons with a custom shape
        colorButtonList.add(new ColorButton(new ImageButton(App.getAppContext()), colors[i]));

        //Here each imagebutton should get its own color.
        Drawable drawable = colorButtonList.get(i).getButton().getBackground();

        if (drawable instanceof GradientDrawable) {
            GradientDrawable gd = (GradientDrawable) drawable.getCurrent();
            gd.setColor(Color.parseColor(colors[i]));
        } else if (drawable instanceof RippleDrawable) {
            RippleDrawable rd = (RippleDrawable) drawable;
            // keep in mind that colors[i] should be a string with the hex representation of a color, like: #F4F4F4
            int color = Color.parseColor(colors[i]);
            rd.setColor(newColorStateList(color));
        }
    }
    return colorButtonList;
}


private static ColorStateList newColorStateList(int color) {
    int[][] states = new int[][] {
            new int[] { android.R.attr.state_enabled}, // enabled
            new int[] {-android.R.attr.state_enabled}, // disabled
    };

    int[] colors = new int[] {
            color, color
    };

    return new ColorStateList(states, colors);
}

}

This is from my recyclerView Adapter class where I infalte layout.item_colorbutton. <- this is at the top of this post

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    Context context = parent.getContext();
    LayoutInflater inflater = LayoutInflater.from(context);

    //inflates the custom layout for a button
    View colorButtonView = inflater.inflate(R.layout.item_colorbutton, parent, false);

    //Return a new holder instance of a colorButton
    ViewHolder viewHolder = new ViewHolder(colorButtonView);
    return viewHolder;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your problem is that in your case getBackground() is returning a RippleDrawable, not a GradientDrawable. Both extend Drawable, but you can not cast one to the other. Try this:

public List<ImageButton> initColorButtons(){
    colorButtonList = new ArrayList<>();

    //here we retrive all colors from color.xml
    Resources resources = App.getAppContext().getResources();
    String colors[] = resources.getStringArray(R.array.backgroundcolors);

    for(int i=0; i<colors.length; i++){
        //Creates 12 ImageButtons with a custom shape
        colorButtonList.add(new ColorButton(new ImageButton(App.getAppContext()), colors[i]));

        //Here each imagebutton should get its own color.
        Drawable drawable = colorButtonList.get(i).getBackground();

        if (drawable instanceof GradientDrawable) {
            GradientDrawable gd = (GradientDrawable) drawable.getCurrent();
            gd.setColor(Color.parseColor(colors[i]));
        } else if (drawable instanceof RippleDrawable) {
            RippleDrawable rd = (RippleDrawable) drawable;
            // keep in mind that colors[i] should be a string with the hex representation of a color, like: #F4F4F4
            int color = Color.parseColor(colors[i]);
            rd.setColor(newColorStateList(color));
        }
    }
    return colorButtonList;
}

private ColorStateList newColorStateList(int color) {
    int[][] states = new int[][] {
            new int[] { android.R.attr.state_enabled}, // enabled
            new int[] {-android.R.attr.state_enabled}, // disabled
    };

    int[] colors = new int[] {
            color, color
    };

    return new ColorStateList(states, colors);
}

Result:

screenshot

You can read more on how to create a ColorStateList in this SO question.

EDIT: In order to correctly modify the buttons you create with the method onCreateViewHolder, you need to implement onBindViewHolder in your Adapter and change the color of your buttons there.

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
        Drawable drawable = holder.getBackground();

        if (drawable instanceof GradientDrawable) {
            GradientDrawable gd = (GradientDrawable) drawable.getCurrent();
            gd.setColor(Color.parseColor(colors[position]));
        } else if (drawable instanceof RippleDrawable) {
            RippleDrawable rd = (RippleDrawable) drawable;
            int color = Color.parseColor(colors[position]);
            rd.setColor(newColorStateList(color));
        }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...