This looks easy, but I\'m not able to disable an ImageButton
. It continues to receive click events, and its appearance don\'t change like a standard Button woul
Here's the code I use to disable an ImageButton
and make it look grayed out:
/**
* 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 iconResId The 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;
}
Simply call setImageButtonEnabled()
; the only downside is you need the image's resource ID in here because it's not possible to revert a transformed icon back into the original.
ImageButton
has different inheritance chain meaning it does not extend Button
:
ImageButton
< ImageView
< View
It continues to receive click events
Here is what happens when you set a click listener for the View
:
public void setOnClickListener(OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
mOnClickListener = l;
}
So if you set a listener the android:clickable="false"
changes to android:clickable="true"
.
and its appearance don't change like a standard Button would
You should supply a drawable state list to the view so it could set an appropriate image based on android:enabled
. Do you have this? Or you have the only image for your button?
EDIT: You can find info on StateListDrawable here. android:state_enabled
is what you need to use in the list in order to tell the OS what image to use for that state.
EDIT2: Since you really need to add a listener you can make a check inside of the listener if (!isEnabled()) { return; } else { /* process the event */ }
.
I managed to build a solution inspired by Oleg Vaskevich's answer, but without the need to pass drawable resource ID to setEnabled().
Here is Kotlin code, inside of utility module:
fun Drawable.deepCopy(): Drawable =
constantState?.newDrawable()?.mutate() ?:
throw RuntimeException("Called on null Drawable!")
fun Drawable.toGrayscale(): Drawable =
deepCopy().apply { setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN) }
fun ImageButton.setAndShowEnabled(enabled: Boolean) {
if (enabled == isEnabled)
return
isEnabled = enabled
if (enabled) {
setImageDrawable(tag as Drawable)
}
else {
if (tag == null)
tag = drawable
setImageDrawable(drawable.toGrayscale())
}
}
It can be used like this:
val button: ImageButton = findViewById(...)
// ...
button.setAndShowEnabled(false)
// launch async operation
GlobalScope.launch {
// do work here
// unblock button
button.setAndShowEnabled(true)
}
Make sure there is no view with same id in your view hierarchy and you do not add any click listener to that view.
Taking advantage of the Oleg Vaskevich's answer. Can be made an answer for Kotlin.
Make a Extension Function for ImageButton, this way:
/**
* 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 iconResId The icon ID
*/
fun ImageButton.setButtonEnabled(enabled: Boolean, iconResId: Int) {
isEnabled = enabled
val originalIcon = context.resources.getDrawable(iconResId)
val icon = if (enabled) originalIcon else convertDrawableToGrayScale(originalIcon)
setImageDrawable(icon)
}
And you get a little less reliant on providing Context
As other answers have said, you cannot disable an ImageButton
in the layout XML as you can a Button
, but you can disable both the same way at runtime:
In Java:
button.setEnabled(false); // setEnabled(boolean) on TextView
imgButton.setEnabled(false); // setEnabled(boolean) on View
In both cases the button is disabled -- no click events get to its onClickListener
.
You can also change the icon color of the disabled ImageButton
the same way you change the text color on a disabled Button
, assuming the icon is tintable.
In the layout XML:
<Button
...
android:textColor="@drawable/button_color_selector" />
<ImageButton
...
android:tint="@drawable/button_color_selector" />
Now setEnable(boolean)
on the Button
or ImageButton
changes the text or icon color according to the states in your button_color_selector.xml