Android: Change Shape Color in runtime
Asked Answered
V

8

57

I have a drawable that i use as a Background for a LinearLayout. I would like to change the color of this Shape in runtime. I have tried using several methods.. but none work.

I've followed the approach described here: http://www.anddev.org/android-2d-3d-graphics-opengl-problems-f55/change-shape-drawable-solid-color-t16798.html

But have the same problem... it doesnt crashes.. but the color doesnt change!

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#00A6C1" />
    <corners android:radius="@dimen/square_corners" />
</shape>

Snippet of code:

GradientDrawable drawable = (GradientDrawable) activity.getResources().getDrawable(R.drawable.blue_square_shape);


int color = ((Application) getApplication()).getColor();
drawable.setColor(color);

block.findViewById(R.id.blockSquare).setBackgroundDrawable(drawable);

findViewById(R.id.blockSquare).postInvalidate();

Any clue? I've passed the whole day googling... and it's getting pretty annoying...

UPDATE:

When i try to do the same to this Shape:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/shape" android:shape="rectangle">
    <gradient android:startColor="#1FBCCF" android:endColor="#06A4C1"
        android:angle="270" />
    <corners android:topLeftRadius="@dimen/footer_corners"
        android:topRightRadius="@dimen/footer_corners" />
</shape>

The color turns to black... what i guess tells it can be changed...

Vincenza answered 9/5, 2011 at 18:20 Comment(7)
Just a guess. The Drawable isn't mutatable, so you need to create a copy, and mutate that one.Selfdevotion
Why then it turns to black on the second example?! :-SVincenza
What color are you setting it to? Black?Selfdevotion
No. Yellow. One thing i've noticed is that the color that i'm passing is RGB and it expects ARGB. The color that i'm using is a parsing of a string #RRGGBB.Vincenza
Do in that case use binary OR of your parsed number and 0xFF000000.Selfdevotion
No success so far.. i'm using now a new Shape created in runtime. Still this is not the solution i was looking for. Changing the current color it want i really want..Vincenza
I think all the answers here change the background color, but not color of the image. Im i right? can anyone tell me please? I tried all the solutions here and also on same questions on stackoverflow, but they change only background color in may case. So i think, we can only change background color, but not the images color. I'm I right?Barogram
M
35

See if something similar to this works for you:

TextView tv2 = (TextView) rl.findViewById(R.id.toggle_indicator);
/* Refer to http://developer.android.com/reference/android/graphics/drawable/GradientDrawable.html#mutate()
to understand why we need to mutate the GradientDrawable*/
GradientDrawable sd = (GradientDrawable) tv2.getBackground().mutate();
sd.setColor(0xff999999);
sd.invalidateSelf();

In my case I have a TextView which has a ShapeDrawable as a background. I wanted to change its color and managed to make this work. Inexplicably, tv2.getBackground() returns a GradientDrawable instead of a ShapeDrawable -- this has been reported elsewhere as well.

Edit: About the color, try setting an alpha value of 0xff. If you notice, even in my code above the setColor() function takes an extra hex value apart from the regular RGB hex value. This is for Alpha/Opacity. If this is set to 0x00 the Drawable will have a black color, irrespective of the RGB (assuming that your background color is black). 0x00 is a completely transparent object & 0xff is a completely opaque object.

Manageable answered 15/12, 2011 at 22:13 Comment(4)
@NeTeInStEiN take a look at the explanation for black color I just added. If this solves your problem completely, I'd request you to choose this as the right answer.Manageable
+1 @SaurabhNanda for solving my problem. Very strange it is a GradientDrawable isn't it!Papaya
@SaurabhNanda Could you help with something similar in my question: #35399158Dichy
In my opinion this is a crucial part of any answer. In my case the invalidateSelf() was crucial.Ruben
V
42

I'm now creating a Drawable like the one pre-compiler.. as i couldn't change the color to anything but black, even after trying the hex OR described below.

The new code:

ShapeDrawable footerBackground = new ShapeDrawable();

// The corners are ordered top-left, top-right, bottom-right,
// bottom-left. For each corner, the array contains 2 values, [X_radius,
// Y_radius]
float[] radii = new float[8];
radii[0] = activity.getResources().getDimension(R.dimen.footer_corners);
radii[1] = activity.getResources().getDimension(R.dimen.footer_corners);

radii[2] = activity.getResources().getDimension(R.dimen.footer_corners);
radii[3] = activity.getResources().getDimension(R.dimen.footer_corners);

footerBackground.setShape(new RoundRectShape(radii, null, null));

int color = ((Application) activity.getApplication()).getColor();

footerBackground.getPaint().setColor(color);

views.setBackgroundDrawable(footerBackground);

Anyway this is a fix.. a solution for the first question is what i'm really looking for! I'll appreciate any help of course!

Vincenza answered 11/5, 2011 at 11:3 Comment(1)
I find using Shape Drawable technique for generating rounded corners is a better solution than using Gradient Drawable rounded corner method. There seems to be a bug with Gradient Drawable whereby some corners are not rounded (causing button to appear clipped) when the app launches and the screen jitters once. Shape Drawable rounded corner works 100% for me.Shulock
M
35

See if something similar to this works for you:

TextView tv2 = (TextView) rl.findViewById(R.id.toggle_indicator);
/* Refer to http://developer.android.com/reference/android/graphics/drawable/GradientDrawable.html#mutate()
to understand why we need to mutate the GradientDrawable*/
GradientDrawable sd = (GradientDrawable) tv2.getBackground().mutate();
sd.setColor(0xff999999);
sd.invalidateSelf();

In my case I have a TextView which has a ShapeDrawable as a background. I wanted to change its color and managed to make this work. Inexplicably, tv2.getBackground() returns a GradientDrawable instead of a ShapeDrawable -- this has been reported elsewhere as well.

Edit: About the color, try setting an alpha value of 0xff. If you notice, even in my code above the setColor() function takes an extra hex value apart from the regular RGB hex value. This is for Alpha/Opacity. If this is set to 0x00 the Drawable will have a black color, irrespective of the RGB (assuming that your background color is black). 0x00 is a completely transparent object & 0xff is a completely opaque object.

Manageable answered 15/12, 2011 at 22:13 Comment(4)
@NeTeInStEiN take a look at the explanation for black color I just added. If this solves your problem completely, I'd request you to choose this as the right answer.Manageable
+1 @SaurabhNanda for solving my problem. Very strange it is a GradientDrawable isn't it!Papaya
@SaurabhNanda Could you help with something similar in my question: #35399158Dichy
In my opinion this is a crucial part of any answer. In my case the invalidateSelf() was crucial.Ruben
T
31
GradientDrawable background = (GradientDrawable) titleTextView.getBackground();
background.setColor(getResources().getColor(R.color.some_color));

The setColor method correctly requests a redraw on the element (If in xml you used the <shape> element it will always become a GradientDrawable)

Teaching answered 14/8, 2012 at 8:53 Comment(2)
Make sure you don't re-use this drawable anywhere else before changing it's color to the correct one. On API<21 the drawable keeps it's latest color set.Counterforce
thanks brother i was wondering for almost 2 hours for this silly thingsUnited
P
9

R.drawable.library_cirecle

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/outerRectangle">
    <shape android:shape="oval" >
        <solid android:color="#FCD366" />

        <stroke
            android:width="1dp"
            android:color="@android:color/darker_gray" />
    </shape>
</item>

Change color in code

Drawable tempDrawable = getResources().getDrawable(R.drawable.library_cirecle);
LayerDrawable bubble = (LayerDrawable) tempDrawable; (cast to root element in xml)
GradientDrawable solidColor = (GradientDrawable) bubble.findDrawableByLayerId(R.id.outerRectangle);
solidColor.setColor(colorToPaint);
imageView.setImageDrawable(tempDrawable);
Palm answered 12/5, 2015 at 8:58 Comment(1)
sorry colorToPaint = getResources().getColor()Palm
M
7

There is an easier way:

ShapeDrawable drawable = new ShapeDrawable();
drawable.getPaint().setColor(getResources().getColor(R.color.blue));
getActionBar().setBackgroundDrawable(drawable);
Mood answered 13/11, 2014 at 8:53 Comment(3)
Your answer has nothing to do with the question... read more carefully.Vincenza
@NeTeInStEiN: It has everything to do with the question. You should try it before you dismiss it next time.Lanta
@Mood You could explain better your answerAnsell
S
1

This is what I'm doing in a live wallpaper where I modify a Drawable at runtime:

this.original = DrawableFactory.getDrawable(getContext().getResources(), objectName)[0];
originalBitmap = original.getBitmap();
copy = new BitmapDrawable(getContext().getResources(), original.getBitmap().copy(Bitmap.Config.ARGB_8888, true));
copyCanvas = new Canvas(copy.getBitmap());

Edit: Type declarations:

public Bitmap originalBitmap;
public BitmapDrawable original;
public BitmapDrawable copy;
public Canvas copyCanvas;

Edit 2:

Try this in that case:

int color = (0xFF000000 | yourParsedColor)

Then set that color.

Selfdevotion answered 9/5, 2011 at 18:29 Comment(3)
What type is original and copy ?Vincenza
Even with it.. it only turns black :-(Vincenza
Sigh, I would need to debug it in that case, but that is unfortunately not something that I'd like to do :(Selfdevotion
T
-1

My current fix involves having a drawable without the color option. I put it inside a frame layout, and then set the background color of the frame layout object dynamically. It's still technically a 'fix,' but it's the most simple option in my opinion.

Layout File:

<FrameLayout
    android:id="@+id/dateLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/SecondaryGreen">

    <ImageView
        android:id="@+id/dateBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/date_rectangle" />

</FrameLayout>

Date Rectangle Drawable File:

<shape xmlns:android="http://schemas.android.com/apk/res/android" ><size android:width="50dp" android:height="50dp"/><corners android:radius="5dp"/></shape>

Dynamic Rendering:

mHolder.dateLayout.setBackgroundColor(getResources().getColor(R.color.SecondaryGreen));
Tenant answered 25/3, 2015 at 22:17 Comment(1)
Sorry guys. Didn't realize you can't shape your shape (i.e. My shape has rounded corners, but the background color is filled in the entire space so you can't tell). This fix will only work for shapes that fit a frame, not round shapes or rectangles with rounded corners.Tenant
D
-1

Set GradientDrawable Shape color using hex code/value
Simply prefix 0x to hexadecimal color value.

    GradientDrawable shape =  new GradientDrawable();
    shape.setCornerRadius( 16 );
    shape.setColor(0xff33b5e5);
    ButtonStartSurvey.setBackground(shape);
Daltondaltonism answered 22/12, 2016 at 9:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.