Disable an ImageButton

后端 未结 7 1794
小蘑菇
小蘑菇 2020-12-14 01:51

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

相关标签:
7条回答
  • 2020-12-14 01:56

    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.

    0 讨论(0)
  • 2020-12-14 01:59

    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 */ }.

    0 讨论(0)
  • 2020-12-14 02:08

    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)
    }
    
    0 讨论(0)
  • 2020-12-14 02:09

    Make sure there is no view with same id in your view hierarchy and you do not add any click listener to that view.

    0 讨论(0)
  • 2020-12-14 02:13

    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

    0 讨论(0)
  • 2020-12-14 02:14

    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

    0 讨论(0)
提交回复
热议问题