3

In Android, I have a button that contains an image and text. When the button is disabled, the text is automatically grayed out, but the image stays the same. Is it possible to have the image dimmed when the button is disabled without having two separate images?

Aleks G
  • 56,435
  • 29
  • 168
  • 265

3 Answers3

6

In your code, you can also use a ColorFilter, specifically a PorterDuffColorFilter, with a mode of DARKEN for example.

For the opacity of a Drawable you can also use setAlpha().

To obtain the Drawables (bitmaps, ...) in question button.getCompoundDrawables() can be used.

I am not sure if this will work, but maybe you want to investigate if it's possible to configure your button's bitmap via a state list, which in turn refers to two drawables of which one refers to a filter. Pretty complex, but if you can't/won't use code for that it may be feasible to do it in XML this way.

JimmyB
  • 12,101
  • 2
  • 28
  • 44
  • Probably the right approach - but how do I get the bitmap from the button and then set it back to the button? – Aleks G Jan 26 '12 at 16:49
  • Usually via something like `((Drawable)button.findViewById( myImageId )).setAlpha(...)`, but I don't know how your button is built. Is it a customized 'regular' button, an `ImageButton`, some kind of `CompoundButton`? – JimmyB Jan 26 '12 at 20:27
  • It's a regular Button. The image is specified in the XML as `android:topDrawable` – Aleks G Jan 27 '12 at 08:42
  • I'm giving this +1 as it pushed my search in the right direction – Aleks G Jan 27 '12 at 12:25
  • 1
    Using a StateListDrawable with the same bitmap with a unique color filter for each state would be the best option. Unfortunately, color filters don't work on the drawables added to the StateListDrawable. (See http://stackoverflow.com/questions/6018602/statelistdrawable-to-switch-colorfilters?rq=1). My solution was to create factory that re-draws the bitmap with a color filter into a new bitmap for each desired state. – SurlyDre Dec 03 '13 at 18:11
2

Finally got it!

I haven't found a way to do this by setting the image in XML, so have to set it in the code. Here's what I got that works:

Button btnObjects = (Button)this.findViewById(R.id.button_objects);
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.button_image_objects);
if( <button needs to be disabled> )
{
    btnObjects.setEnabled(false);
    bm = adjustOpacity(bm, 128);
}
else
{
    btnObjects.setEnabled(true);
}
btnObjects.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(bm), null, null);

//and here's where the magic happens
private Bitmap adjustOpacity(Bitmap bitmap, int opacity)
{
    //make sure bitmap is mutable (copy of needed)
    Bitmap mutableBitmap = bitmap.isMutable()
                           ? bitmap
                           : bitmap.copy(Bitmap.Config.ARGB_8888, true);

    //draw the bitmap into a canvas
    Canvas canvas = new Canvas(mutableBitmap);

    //create a color with the specified opacity
    int colour = (opacity & 0xFF) << 24;

    //draw the colour over the bitmap using PorterDuff mode DST_IN
    canvas.drawColor(colour, PorterDuff.Mode.DST_IN);

    //now return the adjusted bitmap
    return mutableBitmap;
}
Aleks G
  • 56,435
  • 29
  • 168
  • 265
1

In the above scenario i guess you can use selector.xml for the background of your button. You can then use <item android:state_enabled="false" android:color="@color/testcolor3" /> tag accordingly.

Relsell
  • 771
  • 6
  • 18
  • This is not going to help me at all. I need to adjust the opacity of the image, not the background colour of the button (which is fully transparent anyway) – Aleks G Jan 26 '12 at 16:51