web-dev-qa-db-ja.com

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に変更すると、期待どおりに機能することです。ボタンは無効になり、クリックできなくなります。わかりません。誰かがアイデアを持っていますか?

25
Dalmas

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 here に関する情報を見つけることができます。 _Android:state_enabled_は、その状態に使用するイメージをOSに指示するためにリストで使用する必要があるものです。

EDIT2:本当にリスナーを追加する必要があるので、リスナー内でチェックを行うことができますif (!isEnabled()) { return; } else { /* process the event */ }

17
Vit Khudenko

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が必要なことです。

45
Oleg Vaskevich

ビュー階層に同じIDのビューがないことを確認し、そのビューにクリックリスナーを追加しないでください。

2
a.ch.

画像ボタンを無効にする場合は、クリックイベントで、プロパティ「setEnabled」をfalseに設定します。

例:imgButton.setEnabled(false);

2
Roman Marius

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

また、Contextの提供への依存度がやや低くなります。

2
Mário Henrique

私はなんとかOleg Vaskevichの answer に触発されたソリューションを構築できましたが、描画可能リソース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)
}
1
Ivan Mikhnovich

他の回答が述べたように、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" />
_

ButtonまたはImageButtonsetEnable(boolean)は、_button_color_selector.xml_の状態に応じてテキストまたはアイコンの色を変更します

0
MarcS