web-dev-qa-db-de.com

Wie kann ich die deaktivierte Farbe der Schaltfläche mit AppCompat einrichten?

Ich benutze diesen style um background Farbe meiner Button zu ändern:

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

Und in 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"/>

Es klappt. Wenn ich jedoch setEnabled(false) für diese Button-Datei anrufe, behält sie dieselbe Farbe. Wie kann ich diesen Fall handhaben?

29
Alexandr

Sie verwenden den Widget.AppCompat.Button.Colored-Stil nicht korrekt. Sie verwenden einen übergeordneten Stil (Widget.AppCompat.Button.Colored), wenden diesen jedoch als Design an. Dies bedeutet effektiv, dass der Widget.AppCompat.Button.Colored-Teil vollständig ignoriert wird und Sie stattdessen lediglich die Standardfarbe der Schaltfläche ändern (was funktioniert, was aber nicht den deaktivierten Fall behandelt).

Verwenden Sie stattdessen eine ThemeOverlay und wenden Sie den Colored-Stil separat an:

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

Wie in diese Antwort bei Verwendung des Widget.AppCompat.Button.Colored-Stils erwähnt, wird die deaktivierte Farbe von colorButtonNormal und die aktivierte Farbe von colorAccent gesteuert. Durch die Verwendung von ThemeOverlay.AppCompat.Dark wird die textColor automatisch in dunkel geändert, was bedeutet, dass Sie die benutzerdefinierte ThemeOverlay möglicherweise gar nicht benötigen.

72
ianhanniballake

Wenn Sie die akzeptierte Lösung mit einem benutzerdefinierten Widget kombinieren, können Sie eine Schaltfläche anzeigen, die durch Einstellen des Alphas deaktiviert erscheint. Dies sollte für jede Tasten- und Textfarbenkombination funktionieren:

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

anstatt Farbe für Ihre Schaltfläche zu verwenden, sollten Sie einen Hintergrund mit Selektoren verwenden. Hier ist der Demo-Code

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

Wenn Sie sich programmatisch geändert haben, müssen Sie so handeln:

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

ODER

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

Derzeit verwende ich die folgenden Einstellungen für 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>

und

<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

Komplette Lösung von ianhanniballake 'answer und Joe Bowbeer ' Kommentar:

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

Und wo auch immer Sie die Schaltfläche verwenden:

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

Das hat wirklich gut für mich funktioniert

1
Seven

Die Kotlin-Implementierung von @ meanmans Antwort oben, das Anpassen von Alpha ist bei weitem der einfachste Weg und alle meine Touch-Ripple-Effekte funktionieren weiterhin wie zuvor:

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