Отключить ImageButton
Это выглядит просто, но я не могу отключить 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
, тогда он работает так, как ожидалось. Кнопка становится отключенной и непривлекательной. Я не понимаю. У кого-нибудь есть идея?
Ответы
Ответ 1
ImageButton
имеет другую цепочку наследования, то есть не расширяет Button
:
ImageButton
< ImageView
< View
Он продолжает получать события клика
Вот что происходит, когда вы устанавливаете прослушиватель щелчков для View
:
public void setOnClickListener(OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
mOnClickListener = l;
}
Поэтому, если вы установите слушателя, android:clickable="false"
изменится на android:clickable="true"
.
и его внешний вид не меняется, как стандартная кнопка
Вы должны предоставить список отображаемых состояний для представления, чтобы оно могло установить соответствующее изображение на основе android:enabled
. У тебя есть это? Или у вас есть единственное изображение для вашей кнопки?
РЕДАКТИРОВАТЬ: Вы можете найти информацию о StateListDrawable здесь. android:state_enabled
- это то, что вам нужно использовать в списке, чтобы указать ОС, какой образ использовать для этого состояния.
РЕДАКТИРОВАТЬ 2: Поскольку вам действительно нужно добавить слушателя, вы можете проверить внутри слушателя, if (!isEnabled()) { return; } else {/* process the event */}
if (!isEnabled()) { return; } else {/* process the event */}
.
Ответ 2
Вот код, который я использую, чтобы отключить 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 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()
; единственный недостаток - вам нужен идентификатор ресурса изображения здесь, потому что невозможно вернуть преобразованный значок обратно в оригинал.
Ответ 3
Удостоверьтесь, что в иерархии представлений нет одного и того же идентификатора, и вы не добавляете к нему никакого просмотра.
Ответ 4
если вы хотите отключить кнопку изображения, в событии клика, установите для свойства "setEnabled" значение false
Пример: imgButton.setEnabled(false);
Ответ 5
Воспользовавшись ответом Олега Васкевича. Можно сделать ответ для Котлина.
Создайте функцию расширения для 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)
}
И вы становитесь чуть менее зависимым от предоставления контекста
Ответ 6
Мне удалось создать решение, вдохновленное ответом Олега Васкевича, но без необходимости передавать 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)
}
Ответ 7
Как уже говорили другие ответы, вы не можете отключить 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