Отключить кнопку ImageButton - PullRequest
       15

Отключить кнопку ImageButton

23 голосов
/ 19 ноября 2011

Это выглядит просто, но я не могу отключить ImageButton. Он продолжает получать события нажатия, и его внешний вид не меняется, как это делает стандартная кнопка.

Есть несколько похожих вопросов по SO, но они мне не помогают.

Даже с очень простым макетом, подобным этому:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <ImageButton
        android:id="@+id/btn_call"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:clickable="false"
        android:enabled="false"
        android:src="@android:drawable/sym_action_call" />

</LinearLayout>

Кнопка все еще включена, и я могу нажать на нее.

Что странно, если я заменю ImageButton на простой Button, тогда он будет работать, как и ожидалось. Кнопка становится отключенной и не нажатой. Я не понимаю У кого-нибудь есть идея?

Ответы [ 7 ]

43 голосов
/ 03 января 2013

Вот код, который я использую, чтобы отключить ImageButton и сделать его серым:

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

Просто позвоните setImageButtonEnabled();Единственным недостатком является то, что вам нужен идентификатор ресурса изображения здесь, потому что невозможно вернуть преобразованный значок обратно в оригинал.

16 голосов
/ 19 ноября 2011

ImageButton имеет другую цепочку наследования, то есть не расширяется Button:

ImageButton <<code>ImageView <<code>View

Он продолжает получать события клика

Вот что происходит, когда вы устанавливаете прослушиватель щелчков для View:

public void setOnClickListener(OnClickListener l) {
    if (!isClickable()) {
        setClickable(true);
    }
    mOnClickListener = l;
}

Таким образом, если вы установите слушателя, android:clickable="false" изменится на android:clickable="true".

и его внешний вид не меняется, как стандартная кнопка

Вы должны предоставить списку нарисованных состояний для представления, чтобы оно могло установить соответствующее изображение на основе android:enabled. У тебя есть это? Или у вас есть единственное изображение для вашей кнопки?

EDIT: Вы можете найти информацию о StateListDrawable здесь . android:state_enabled - это то, что вам нужно использовать в списке, чтобы указать ОС, какой образ использовать для этого состояния.

EDIT2: так как вам действительно нужно добавить слушателя, вы можете проверить внутри слушателя if (!isEnabled()) { return; } else { /* process the event */ }.

2 голосов
/ 01 октября 2012

Если вы хотите отключить кнопку изображения, при событии щелчка установите для свойства "setEnabled" значение false

Пример: imgButton.setEnabled(false);

2 голосов
/ 19 ноября 2011

Убедитесь, что в вашей иерархии представлений нет представления с таким же идентификатором, и вы не добавляете прослушиватель щелчков для этого представления.

1 голос
/ 31 марта 2018

Воспользовавшись ответом Олега Васкевича .Можно получить ответ для Kotlin.

Создайте функцию расширения для ImageButton, таким образом:

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

И вы получите немного меньшую зависимость от предоставления Контекст

0 голосов
/ 22 января 2019

Как уже говорилось в других ответах, вы не можете отключить ImageButton в XML макета, как вы можете Button, но вы можете отключить оба одинаково во время выполнения:

В Java:

button.setEnabled(false);     // setEnabled(boolean) on TextView
imgButton.setEnabled(false);  // setEnabled(boolean) on View

В обоих случаях кнопка отключена - никакие события щелчка не доходят до onClickListener.

Вы также можете изменить цвет значка для отключенного ImageButton так же, как вы изменили цвет текста для отключенного Button, предполагая, что значок можно изменять.

В макете XML:

<Button
    ...
    android:textColor="@drawable/button_color_selector" />


<ImageButton
    ...
    android:tint="@drawable/button_color_selector" />

Теперь setEnable(boolean) на Button или ImageButton изменяет цвет текста или значка в соответствии с состояниями в button_color_selector.xml

0 голосов
/ 15 ноября 2018

Мне удалось создать решение, вдохновленное ответом Олега Васкевича , но без необходимости передавать ID ресурса для рисования в setEnabled ().

Вот код Kotlin внутри служебного модуля:

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())
    }
}

Может использоваться следующим образом:

val button: ImageButton = findViewById(...)
// ...
button.setAndShowEnabled(false)

// launch async operation
GlobalScope.launch {
    // do work here

    // unblock button
    button.setAndShowEnabled(true)
}
...