web-dev-qa-db-fra.com

Comment configurer la couleur désactivée du bouton avec AppCompat?

J'utilise ce style pour changer fond couleur de ma Button:

<style name="AccentButton" parent="Widget.AppCompat.Button.Colored">
    <item name="colorButtonNormal">@color/colorAccent</item>
    <item name="Android:textColor">@color/white</item>
</style>

Et dans layout :

    <Button
        Android:id="@+id/login_button"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:text="@string/fragment_login_login_button"
        app:theme="@style/AccentButton"/>

Ça marche. Mais quand j'appelle setEnabled(false) sur cette Button, elle garde la même couleur. Comment puis-je gérer ce cas?

29
Alexandr

Vous n'utilisez pas le style Widget.AppCompat.Button.Colored correctement. Vous utilisez un style parent (Widget.AppCompat.Button.Colored), mais vous l'appliquez en tant que thème. Cela signifie effectivement que la partie Widget.AppCompat.Button.Colored est entièrement ignorée et que vous ne faites que changer la couleur par défaut du bouton (ce qui fonctionne, mais ne gère pas le cas désactivé).

À la place, vous devez utiliser une variable ThemeOverlay et appliquer le style Colored séparément:

<style name="AccentButton" parent="ThemeOverlay.AppCompat.Dark">
   <!-- customize colorButtonNormal for the disable color -->
   <!-- customize colorAccent for the enabled color -->
</style>

<Button
    Android:id="@+id/login_button"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:text="@string/fragment_login_login_button"
    Android:theme="@style/AccentButton"
    style="@style/Widget.AppCompat.Button.Colored"/>

Comme mentionné dans cette réponse sur l'utilisation du style Widget.AppCompat.Button.Colored , la couleur désactivée est contrôlée par colorButtonNormal et la couleur activée est contrôlée par colorAccent. En utilisant le ThemeOverlay.AppCompat.Dark, la textColor devient automatiquement sombre, ce qui signifie que vous n'avez peut-être pas besoin de la ThemeOverlay personnalisée.

72
ianhanniballake

En combinant la solution acceptée avec un widget personnalisé, nous pouvons avoir un bouton qui semble désactivé en définissant l'alpha. Cela devrait fonctionner pour toute combinaison de couleur de bouton et de texte:

public class ButtonWidget extends AppCompatButton {

    public ButtonWidget(Context context) {
        super(context);
    }

    public ButtonWidget(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ButtonWidget(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setEnabled(boolean enabled) {
        setAlpha(enabled ? 1 : 0.5f);
        super.setEnabled(enabled);
    }

}
9
Meanman

au lieu d'utiliser la couleur pour votre bouton, vous devriez utiliser un fond avec des sélecteurs. Voici le code de démonstration

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:state_enabled="true">
        <shape Android:shape="rectangle">
            <solid Android:color="@color/yourEnabledColor" />
        </shape>
    </item>
    <item Android:state_enabled="false">
        <shape Android:shape="rectangle">
            <solid Android:color="@color/yourDisabledColor" />
        </shape>
    </item>
</selector>
6
Awais Ahmad

Lorsque vous avez changé par programme, vous devez agir de la sorte:

button = new Button(new ContextThemeWrapper(ActiVityName.this, R.style.AccentButton));

OU

if (button.isEnabled())
    button.getBackground().setColorFilter(Color.Black, PorterDuff.Mode.MULTIPLY);
else
    button.getBackground().setColorFilter(null);
5
Amit Vaghela

Actuellement, j'utilise les paramètres suivants pour Android API 15+.

/res/color/btn_text_color.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item Android:color="#42000000" Android:state_enabled="false" />
  <item Android:color="#ffffff" />
</selector>

/res/values/styles.xml

<style name="ColoredButton" parent="Widget.AppCompat.Button.Colored">
    <item name="Android:textColor">@color/btn_text_color</item>
</style>

et

<Button
    Android:id="@+id/button"
    style="@style/ColoredButton"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="button" />
4
Milan Hlinák

Solution complète allant de ianhanniballake 'answer et Joe Bowbeer ' commentaire:

/res/values/styles.xml

<style name="AccentButton" parent="ThemeOverlay.AppCompat.Dark">
    <!-- customize colorAccent for the enabled color -->
    <!-- customize colorControlHighlight for the enabled/pressed color -->
    <!-- customize colorButtonNormal for the disabled color -->
    <item name="Android:buttonStyle">@style/Widget.AppCompat.Button.Colored</item>
</style>

Et partout où vous utilisez le bouton:

<Button
    Android:id="@+id/login_button"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:text="@string/fragment_login_login_button"
    Android:theme="@style/AccentButton"/>

Cela a fonctionné vraiment bien pour moi

1
Seven

L'implémentation en Kotlin de la réponse de @ meanman ci-dessus, l'ajustement de l'alpha est de loin le moyen le plus simple à suivre et tous mes effets d'entraînement au toucher fonctionnent toujours comme avant:

import Android.content.Context
import Android.support.v7.widget.AppCompatButton
import Android.util.AttributeSet

class FadedDisableButton : AppCompatButton {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun setEnabled(enabled: Boolean) {
        alpha = when {
            enabled -> 1.0f
            else -> 0.5f
        }
        super.setEnabled(enabled)
    }
}
0
ChrisPrime