Android ImageButton with disabled UI feel

AndroidImage

Android Problem Overview


I have an ImageButton which is disabled (non clickable or set as disabled). I want to give an UI feel to the user that it is disabled without using any other image.

Is there any way to do this?

Android Solutions


Solution 1 - Android

Unlike a regular Button, an ImageButton or a Button that has an image background is not grayed when disabled. You actually have to use another image or to process it in a way it appears grayed.

Should using another image be ok, you can do this by using a <selector> (here associated to a regular Button but this amongs to the same):

  • /drawable/my_selector.xml:

      <?xml version="1.0" encoding="utf-8"?>
      <selector xmlns:android="http://schemas.android.com/apk/res/android">
          <item android:state_enabled="false"
              android:drawable="@drawable/button_gray" /> ***button_gray is a Drawable image***
          <item android:state_pressed="true"
              android:drawable="@drawable/button_gray" /> 
          <item android:drawable="@drawable/button_red" /> ***button_red is a Drawable image*** 
      </selector>
    

Please note that in a selector the logic applies a sequential way, item per item. Here, button_red is used all the time but when the button is disabled or being pushed.

  • Your layout.xml:

      <Button android:id="@+id/myButton"
              android:background="@drawable/my_selector" ***this is a reference to the selector above ***
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
      />
    

And should using another image be a problem, other answers (such as @Tronman's or @southerton's) give you ways to programmatically process the image in a way it appears grayed.

Solution 2 - Android

@Oleg Vaskevich gave a different solution to the problem here: https://stackoverflow.com/questions/8196206/disable-an-imagebutton

His solution allows you to gray-out an ImageButton without creating additional images or using a <selector>.

/**
 * Sets the image button to the given state and grays-out the icon.
 * 
 * @param ctxt The context
 * @param enabled The state of the button
 * @param item The button item to modify
 * @param iconResId The button's icon ID
 */
public static void setImageButtonEnabled(Context ctxt, boolean enabled, 
        ImageButton item, int iconResId) {

    item.setEnabled(enabled);
    Drawable originalIcon = ctxt.getResources().getDrawable(iconResId);
    Drawable icon = enabled ? originalIcon : convertDrawableToGrayScale(originalIcon);
    item.setImageDrawable(icon);
}

/**
 * Mutates and applies a filter that converts the given drawable to a Gray
 * image. This method may be used to simulate the color of disable icons in
 * Honeycomb's ActionBar.
 * 
 * @return a mutated version of the given drawable with a color filter applied.
 */
public static Drawable convertDrawableToGrayScale(Drawable drawable) {
    if (drawable == null) 
        return null;
    
    Drawable res = drawable.mutate();
    res.setColorFilter(Color.GRAY, Mode.SRC_IN);
    return res;
}

Solution 3 - Android

I preferred overriding the setEnabled() method in the ImageButton to change the image's alpha property accordingly. So when the button is disabled, the image will be partially transparent and more disabled-looking.

public class CustomImageButton extends ImageButton {
    //...

    @Override
    public void setEnabled(boolean enabled) {
        if(this.isEnabled() != enabled) {
            this.setImageAlpha(enabled ? 0xFF : 0x3F);
        }
        super.setEnabled(enabled);
    }
}

Solution 4 - Android

Elaborating on @tronman answer you can also compose a function that will gray out dynamically loaded drawables (i.e. not from resource, - for example loaded from raw svg files and converted to BitmapDrawables on the fly).

/**
 * Sets the specified image buttonto the given state, while modifying or
 * "graying-out" the icon as well
 *
 * @param enabled The state of the menu item
 * @param item The menu item to modify
 * @param originalIcon The drawable
 */
public static void setImageButtonEnabled(Context ctxt, boolean enabled, ImageButton item, Drawable originalIcon) {
    item.setEnabled(enabled);

    Drawable res = originalIcon.mutate();
    if (enabled)
        res.setColorFilter(null);
    else
        res.setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN);
}

If you also have a non-transparent drawable on background (set with android:background) refer to selectors https://stackoverflow.com/questions/5624609/android-how-to-make-a-drawable-selector to also modify background.

Solution 5 - Android

You can set it to non clickable and also set the alpha to show that feeling that you mention.

Solution 6 - Android

Solution using only xml resource files:

    <ImageButton
        style="@style/your-style"
        android:tint="@color/but_color"
        android:src="@drawable/button" />

and color resource but_color (in res/color folder):

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:color="#888" />
    <item android:color="?android:attr/colorAccent" />
</selector>

That is, we set color tint of the button (works fine on each Android version if using AndroidX support library). The tint itself is color-state-list. Set colors as you need, here is grey for disabled state, and accent color from theme for enabled state.
We change only color, and only need one image drawable. But note that entire color of button will be changed.

Solution 7 - Android

In Kotlin you can utilize Extension functions.

fun ImageButton.enable() {
    this.isEnabled = true
    this.imageAlpha = 0xFF
}

fun ImageButton.disable() {
    this.isEnabled = false
    this.imageAlpha = 0x3F
}

myButton.enable()
myButton.disable()

Solution 8 - Android

Using setImageAlpha on the ImageButton, this can be done

While Enabling,

 ((ImageButton) findViewById(R.id.btnImageButton1)).setEnabled(true);
 ((ImageButton) findViewById(R.id.btnImageButton1)).setImageAlpha(0xFF);

while disabling,

 ((ImageButton) findViewById(R.id.btnImageButton1)).setEnabled(false);
 ((ImageButton) findViewById(R.id.btnImageButton1)).setImageAlpha(0x3F);

As @SnoopDougg suggested a custom ImageButton class might be a nice idea extending the ImageButton and setting the ImageAlpha inside; haven't tried yet but.

Solution 9 - Android

public static void setImageButtonEnabled(@NonNull final ImageView imageView,
                                         final boolean enabled) {
    imageView.setEnabled(enabled);
    imageView.setAlpha(enabled ? 1.0f : 0.3f);

    final Drawable originalIcon = imageView.getDrawable();
    final Drawable icon = enabled ? originalIcon : convertDrawableToGrayScale(originalIcon);
    imageView.setImageDrawable(icon);
}

private static Drawable convertDrawableToGrayScale(@NonNull Drawable drawable) {
    final ColorMatrix matrix = new ColorMatrix();
    matrix.setSaturation(0);
    final ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);

    final Drawable mutated = drawable.mutate();
    mutated.setColorFilter(filter);

    return mutated;
}

If you use Kotlin, you can create an Extension Function instead, so it looks more elegant:

fun ImageView.setImageButtonEnabled(enabled: Boolean){
   //Above implementation here
}

and call it using:

yourImageView.setImageButtonEnabled(true/false)

Solution 10 - Android

Kotlin extension function to enable/disable an ImageView/ImageButton without IconResId

fun ImageView.setImageViewEnabled(enabled: Boolean) = if(enabled) {
    drawable.clearColorFilter()
    isEnabled = true
} else {
    drawable.colorFilter = PorterDuffColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN)
    isEnabled = false
}

Solution 11 - Android

Nope, your image is the differentiating factor.. so if you don't want to change the image then you cannot tell whether the image button is disabled, enabled, pressed.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser484155View Question on Stackoverflow
Solution 1 - AndroidShlubluView Answer on Stackoverflow
Solution 2 - AndroidtronmanView Answer on Stackoverflow
Solution 3 - AndroidSnoopDouggView Answer on Stackoverflow
Solution 4 - AndroidsouthertonView Answer on Stackoverflow
Solution 5 - AndroidAndroid BeginnerView Answer on Stackoverflow
Solution 6 - AndroidPointer NullView Answer on Stackoverflow
Solution 7 - AndroidSimView Answer on Stackoverflow
Solution 8 - AndroidToji MathewView Answer on Stackoverflow
Solution 9 - AndroidBitcoin Cash - ADA enthusiastView Answer on Stackoverflow
Solution 10 - AndroidBrayan Armando Yaquian GonzaleView Answer on Stackoverflow
Solution 11 - AndroidbluefalconView Answer on Stackoverflow