禁用图像按钮

发布于 2024-12-17 04:11:29 字数 862 浏览 3 评论 0原文

这看起来很简单,但我无法禁用 ImageButton。它继续接收点击事件,并且其外观不会像标准按钮那样改变。

有一些类似的问题,但它们对我没有帮助。

即使有一个非常简单的布局,如下所示:

<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,那么它就会按预期工作。该按钮将被禁用并且无法单击。我不明白。有人有想法吗?

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 would.

There are some similar questions on SO, but they don't help me.

Even with a very simple layout like this :

<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>

The button is still enabled and I can click it.

What's strange is that if I change the ImageButton to a simple Button, then it works as expected. The button becomes disabled and unclickable. I don't understand. Does anyone have an idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

盗心人 2024-12-24 04:11:29

以下是我用来禁用 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();唯一的缺点是您需要在此处提供图像的资源 ID,因为无法将转换后的图标恢复为原始图标。

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.

遇到 2024-12-24 04:11:29

ImageButton 具有不同的继承链,这意味着它不扩展 Button

ImageButton ImageButton ImageButton ImageView < 查看

继续接收点击事件

以下是为 View 设置点击侦听器时发生的情况:

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

因此,如果您设置侦听器,android:clickable="false" 会更改为android:clickable="true"

其外观不会像标准按钮那样改变

您应该向视图提供一个可绘制状态列表,以便它可以根据 android:enabled 设置适当的图像。你有这个吗?或者您的按钮只有唯一的图像?

编辑:您可以在此处找到有关 StateListDrawable 的信息。 android:state_enabled 是您需要在列表中使用的内容,以便告诉操作系统该状态使用什么图像。

EDIT2:由于您确实需要添加一个侦听器,因此您可以在侦听器内部进行检查 if (!isEnabled()) { return; } else { /* 处理事件 */ }.

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

和影子一齐双人舞 2024-12-24 04:11:29

如果要禁用图像按钮,请在单击事件时将属性“setEnabled”设置为 false

例如: imgButton.setEnabled(false);

if you want to disable an image button,on click event, set the the property "setEnabled" to false

Ex: imgButton.setEnabled(false);

长亭外,古道边 2024-12-24 04:11:29

确保您的视图层次结构中没有具有相同 id 的视图,并且您没有向该视图添加任何点击侦听器。

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

清旖 2024-12-24 04:11:29

利用Oleg Vaskevich的答案。可以为 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)
}

你就可以减少对提供上下文

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

2024-12-24 04:11:29

我设法构建了一个受 Oleg Vaskevich 的 答案 启发的解决方案,但不需要将可绘制资源 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)
}

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)
}
没有伤那来痛 2024-12-24 04:11:29

正如其他答案所说,您不能像禁用 Button 那样在布局 XML 中禁用 ImageButton,但您可以在运行时以相同的方式禁用这两者:

在 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" />

现在,ButtonImageButton 上的 setEnable(boolean) 会根据 中的状态更改文本或图标颜色>button_color_selector.xml

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

笑咖 2024-12-24 04:11:29

为了改进 Ivan 2018 年的答案:这是一个更简单的方法(Kotlin):

   fun ImageButton.setAndShowEnabled(enabled: Boolean) {
    val filter = PorterDuffColorFilter(GRAY, PorterDuff.Mode.SCREEN)
    if (enabled == this.isEnabled)
        return

    this.isEnabled = enabled

    if (enabled) {
        drawable.colorFilter = null  // Removes the filter.
    } else {
        drawable.mutate()   // Repeated calls are no-ops.
        drawable.colorFilter = filter
    }
}

To improve on Ivan's 2018 answer: This is a much simpler method (Kotlin):

   fun ImageButton.setAndShowEnabled(enabled: Boolean) {
    val filter = PorterDuffColorFilter(GRAY, PorterDuff.Mode.SCREEN)
    if (enabled == this.isEnabled)
        return

    this.isEnabled = enabled

    if (enabled) {
        drawable.colorFilter = null  // Removes the filter.
    } else {
        drawable.mutate()   // Repeated calls are no-ops.
        drawable.colorFilter = filter
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文