Lollipops backgroundTint hat keine Auswirkung auf einen Button

82

Ich habe eine Schaltfläche in meiner Aktivität und möchte, dass die Akzentfarbe meines Themas angezeigt wird. Anstatt meine eigenen Drawables zu erstellen, wie wir es vor Lollipop tun mussten, möchte ich natürlich das neue backgroundTintAttribut verwenden.

<Button
    android:id="@+id/btnAddCode"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:backgroundTint="@color/accent"
    android:text="@string/addressInfo_edit_addCode" />

Leider hat es keine Auswirkung, die Schaltfläche bleibt grau.

Ich habe verschiedene Werte für ausprobiert backgroundTintMode, was nichts geändert hat.

Ich habe es auch programmgesteuert in meiner Aktivität versucht, was nichts geändert hat.

addCodeView.findViewById(R.id.btnAddCode).setBackgroundTintList(
     getResources().getColorStateList(R.color.accent));

Warum wird mein Farbton ignoriert?

EDIT: Nur zur Klarstellung, ich teste tatsächlich auf einem Lollipop-Gerät. Andere Widgets (z. B. EditText) werden korrekt und automatisch getönt.

BoD
quelle
3
Dies ist ein Fehler, der für eine zukünftige Version behoben wurde, aber die akzeptierte Lösung funktioniert unter API 21+.
Alanv
Überprüfen Sie diese aktualisierte Antwort
Amit Vaghela

Antworten:

18

Getestet auf API 19 bis API 27

<?xml version="1.0" encoding="utf-8"?>
  <android.support.v7.widget.AppCompatButton 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/retry"
    android:textColor="@android:color/white"
    app:backgroundTint="@android:color/holo_red_dark" />

erzeugt Ausgabe als -

Geben Sie hier die Bildbeschreibung ein

Sahitya Pasnoor
quelle
Dies als akzeptierte Antwort markieren, da ich glaube, dass dies nach einigen Jahren derzeit der offizielle (und beste) Weg ist, dies zu tun. (Kleinere Details: Ich bin mir ziemlich sicher, dass Sie in den meisten Fällen einfach Button anstelle von AppCompatButton verwenden können und es weiterhin funktioniert).
BoD
116

Die schlechten Nachrichten

Wie BoD sagt, ist es bedeutungslos, den Hintergrund eines Buttons in Lollipop 5.0 (API-Level 21) zu tönen.

Die guten Nachrichten

Lollipop 5.1 (API-Level 22) scheint dies behoben zu haben, indem btn_mtrl_default_shape.xml (unter anderem) geändert wurde: https://android.googlesource.com/platform/frameworks/base/+/6dfa60f33ca6018959ebff1efde82db7d2aed1e3%5E !

Die gute Nachricht

Die neue Support-Bibliothek (Version 22.1+) bietet vielen Komponenten, einschließlich AppCompatButton, abwärtskompatible Unterstützung für das Abtönen !

Leider android:backgroundTintfunktioniert die Eigenschaft immer noch nicht (vielleicht mache ich etwas falsch) - also müssen Sie den ColorStateListIn-Code mit einstellen setSupportBackgroundTintList(). Es wäre wirklich schön, wenn wir android:backgroundTintin Zukunft Unterstützung sehen würden . Update : Marcio Granzotto hat kommentiert, dass es app:backgroundTintauf AppCompatButton funktioniert! Beachten Sie app:, dass dies nicht android:der Fall ist, da es sich in der App / Bibliothek befindet.

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <AppCompatButton
        android:id="@+id/mybutton"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="Testing, testing"
        app:backgroundTint="#ff00ff"/>

</LinearLayout>

Ihre Aktivität wird automatisch eine AppCompatButtonanstelle der normalen aufblasen, Buttonwenn Sie es von erben lassen AppCompatActivity.

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AppCompatButton v = (AppCompatButton) findViewById(R.id.mybutton);
        ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});
        v.setSupportBackgroundTintList(csl);
    }
}

Sie sollten das natürlich ColorStateListvon einer Farbressource bekommen, aber ich war faul, also ...

Oh, und vergessen Sie nicht, Ihr App-Thema auf eines der Theme.AppCompatThemen zu stützen, sonst werden die kompatiblen Ansichten sehr, sehr traurig sein ...;)

Dies funktionierte sowohl bei 2.3.7 (Lebkuchen MR1) als auch bei 5.0 (Lollipop 'Classic').

Snild Dolkow
quelle
1
Ich habe gerade ein paar Infos hinzugefügt - vor allem ist es jetzt möglich, mit der neuen Version (22.1) der Support-Bibliothek, die neulich veröffentlicht wurde, eine Tönung der Schaltflächen zu erreichen!
Snild Dolkow
8
Sie können colorButtonNormalmit AppCompat 22.1.1 (das Thema nur für die Schaltflächen einstellen) verwenden, es funktioniert für mich unter 4.4.4 und 5.1.
Hunyadym
2
Haben Sie eine Idee, wie Sie dasselbe für TextView festlegen können?
Android-Entwickler
8
Stattdessen new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});können Sie präziser schreiben ColorStateList.valueOf(0xffffcc00);.
Ashkan Sarlak
5
Sie können android.support.v7.widget.AppCompatButton mit App: backgroundTint auf der XML verwenden
Marcio Granzotto
30

Es scheint, dass das Abtönen einer Ripple Drawable bedeutungslos ist (und der Standardhintergrund einer Schaltfläche ist ein Ripple Drawable).

Nachdem ich mir die Standardschaltfläche der Plattform angesehen hatte, fand ich den "richtigen" Weg, dies zu tun: Sie müssen dies in Ihrem Thema definieren:

    <item name="android:colorButtonNormal">@color/accent</item>

(Natürlich ist dies nur für Level 21+.)

Warnung: Da dies in einem Thema definiert ist, wird für alle Schaltflächen (zumindest alle Schaltflächen in Aktivitäten, die dieses Thema verwenden) die angegebene Farbe verwendet.

Als Bonus können Sie auch die Welligkeitsfarbe ändern, indem Sie Folgendes definieren:

    <item name="android:colorControlHighlight">@color/accent_ripple</item>
BoD
quelle
colorControlHighlightwürde aber viele andere Widgets ändern. Ich bin froh, dass du es geschafft hast.
Natario
5
Sie können dies auf eine einzelne Ansicht anwenden, indem Sie ein Überlagerungsthema definieren (z. B. kein übergeordnetes Thema und nur ein Attribut definiert) und das Attribut android: theme verwenden.
Alanv
1
Wie wird es dann für API 22 und höher behoben? Auch dieser "Fehler" tritt nur in einigen Geräten der API 21 (einschließlich Nexus 5, Galaxy S3) auf
vedant
22

Um Probleme im Zusammenhang mit dem Abtönen unter Android 5.0.x zu beheben, verwende ich Folgendes:

public static void setButtonTint(Button button, ColorStateList tint) {
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP && button instanceof AppCompatButton) {
        ((AppCompatButton) button).setSupportBackgroundTintList(tint);
    } else {
        ViewCompat.setBackgroundTintList(button, tint);
    }
}

Die Unterstützungsmethode wird nur für API 21 und die ViewCompat-Methode für alle anderen Fälle verwendet.

GUG
quelle
@ Marco Verwendung:if (view instanceof TintableBackgroundView) { ((TintableBackgroundView) view).setSupportBackgroundTintList(tint); } else { ViewCompat.setBackgroundTintList(view, tint); }
Schachdork
Dies funktioniert nicht mit einem ImageButton auf Pre-Lollipop-Geräten.
toobsco42
Bei Verwendung von AppCompatButton.setSupportBackgroundTintList () wird eine Flusenwarnung angezeigt. AppCompatButton.setSupportBackgroundTintList kann nur innerhalb derselben Bibliotheksgruppe aufgerufen werden (groupId = com.android.support)
starkej2
Es hat bei mir funktioniert, aber ich musste die Bedingungen umkehren.
Rodrigo Venancio
"kann nur innerhalb derselben Bibliotheksgruppe aufgerufen werden (groupId = com.android.support" warum diese Warnung?
Ferran Negre
22

Normalerweise mache ich das dynamisch mit PorterDuff:

mbutton = (Button) findViewById(R.id.mybutton);
mbutton.getBackground().setColorFilter(anycolor, PorterDuff.Mode.MULTIPLY);

Sie können verschiedene Füllmethoden überprüfen hier und schöne Beispiele hier .

Carlos Borau
quelle
1
Ich habe PorterDuff.Mode.SRC verwendet und es funktioniert perfekt
francisco_ssb
Funktioniert perfekt. In meinem Fall wollte ich den Tönungseffekt für API 17 verwenden, dies hat mir geholfen.
ashishdhiman2007
2
Dies sollte die akzeptierte Antwort sein. Bestätigen Sie die Arbeit an API 20.
Hardanger
19

Verwenden Sie einfach app:backgroundTintanstelle von android:backgroundTint, der Farbton wird unterhalb von Lollipop wirksam. Der Grund hierfür ist die AppCompatActivityVerwendung AppCompatViewInflaterzur automatischen Wechsel - Taste oder Textview zu AppCompatButton oder AppCompatTextView, dann in app:backgroundTintKraft treten.

Geben Sie hier die Bildbeschreibung ein

In meinem Projekt habe ich es benutzt, es hat funktioniert.

Drakeet
quelle
9

Ich denke, Sie müssen sich android:backgroundeingestellt haben, um android:backgroundTintArbeit zu machen .

Um genauer zu sein, kann ich davon ausgehen, dass Sie nicht backgroundTintden Standard-Schaltflächenhintergrund aus Materialthemen verwenden können, der als definiert ist RippleDrawable.

natario
quelle
1
Ich denke du bist richtig. Tatsächlich habe ich den "richtigen" Weg gefunden, um das zu tun, was ich will (siehe meine Antwort).
BoD
3

Ein ähnliches Problem wurde auf Google https://code.google.com/p/android/issues/detail?id=201873 gemeldet

Aber nach der Veröffentlichung der Android Support Library, Revision 23.2.1 (März 2016) ist dieser Fehler behoben.

Problem: FloatingActionButton.setBackgroundTintList (@Nullable ColorStateList-Farbton) ändert die Hintergrundfarbe nicht mehr

Aktualisieren Sie die Support-Bibliothek auf Android Support Library to 23.2.1

Verwenden Sie die unten stehende Design Support Library (23.2.1) und Appcompatwidgets

Materialdesign für Pre-Lollipop-Geräte :

AppCompat (auch bekannt als ActionBarCompat) wurde als Backport der Android 4.0 ActionBar-API für Geräte gestartet, die auf Gingerbread ausgeführt werden. Es bietet eine gemeinsame API-Schicht zusätzlich zur Backport-Implementierung und der Framework-Implementierung. AppCompat v21 bietet eine API und einen Funktionsumfang, die mit Android 5.0 auf dem neuesten Stand sind


Android Support Library 22.1 :

Die Möglichkeit, Widgets bei Verwendung von AppCompat automatisch zu tönen, ist unglaublich hilfreich, um ein starkes Branding und eine starke Konsistenz in Ihrer App zu gewährleisten. Dies erfolgt automatisch beim Aufblasen von Layouts. Ersetzen Sie Button durch AppCompatButton, TextView durch AppCompatTextView usw., um sicherzustellen, dass jedes die Tönung unterstützt. In dieser Version sind diese tönungsbewussten Widgets jetzt öffentlich verfügbar, sodass Sie die Tönungsunterstützung auch dann beibehalten können, wenn Sie eines der unterstützten Widgets in Unterklassen unterteilen müssen.

Amit Vaghela
quelle
3

Verwenden Sie einfach app: backgroundTint anstelle von android: backgroundTint

Smirnov Sergey
quelle
2

Wenn wir uns den Quellcode der Support Library ansehen, sehen wir, dass er normalerweise die bekannten Schaltflächen färbt, aber wenn wir die Form unserer Schaltfläche ändern (ich habe eine runde Schaltfläche), funktioniert der Farbton in API <= 21 nicht in Ordnung. Wir können auch sehen, dass TintManager zur öffentlichen Klasse wurde (appcompat-v7: 23.1.1), sodass wir ColorStateList aus der Standardschaltflächenform (die in 5.0 in Ordnung getönt ist) für das aktuelle Thema übernehmen können (sodass wir das Array nicht erstellen müssen von Farben):

    Context c = ...; // activity
    AppCompatButton ab = ...; // your button
    // works ok in 22+:
    if (Build.VERSION.SDK_INT <= 21) {
        // default appcompat button, that is tinted ok with current theme colors "abc_btn_default_mtrl_shape":
        // ColorStateList tint = TintManager.get(c).getTintList(R.drawable.abc_btn_default_mtrl_shape);
        // Appcompat 23.2 change:
        ColorStateList tint = AppCompatDrawableManager.get().getTintList(c, R.drawable.abc_btn_default_mtrl_shape);
        ab.setSupportBackgroundTintList(tint);
        }
Pavel Biryukov
quelle
seit Appcompat 23.2 haben sie die Klasse geändert (obwohl es öffentlich ist!) TintManager -> AppCompatDrawableManager der Code bleibt fast gleich
Pavel Biryukov
WTF ... getTintList wurde jetzt von öffentlich auf geschützt geändert (Reflektion muss verwendet werden :)
Pavel Biryukov
0

Weil das Attribut backgroundTintnur in API-Level 21 und höher verwendet wird

Fedache
quelle
Mir ist klar, dass ich tatsächlich auf einem Lollipop-Gerät teste. Ich werde die Frage aktualisieren, um dies klar zu machen.
BoD
0

Beachten Sie, dass die am meisten aktualisierte Bibliothek von recyclerview auch diesen Fehler verursachen kann.

Dieser Befehl

  sendBtnView.setBackgroundTintList(colorState)

hat in der Vergangenheit perfekt funktioniert, aber hör auf für mich zu arbeiten. Nach Recherchen stellt sich heraus, dass die Ursache die Bibliothek ist, die zu Gradle-Abhängigkeiten hinzugefügt wurde:

  compile 'com.android.support:recyclerview-v7:+'

Also habe ich versucht, es auf 23.02.1 zu ändern, wie es hier in Amit Vaghela Post empfohlen wurde. Ich wechselte zu

  compile  'com.android.support:recyclerview-v7:23.02.1'

Aber gradle Fehler sagte, dass recyclerview lib diese Version (23.02.1) nicht hat (gradle konnte sie nicht in Jcenter raw.github oder repo finden).

Dann, weil ich wusste, dass der Befehl setBackgroundTintList in der Vergangenheit mit Version 22.02.0 'in allen anderen Bibliotheken, die ich in Gradle-Abhängigkeiten habe, gut funktioniert hat. also ändere ich es auf:

compile   'com.android.support:recyclerview-v7:22.02.0'

Und jetzt funktioniert es wieder.

Udi Reshef
quelle
0

Ich bin nicht sicher, ob dies empfohlen wird, aber Sie können dies versuchen:

Drawable newDrawable = mBtnAction.getBackground();  // obtain Bg drawable from the button as a new drawable
DrawableCompat.setTint(newDrawable, mActivity.getHomeTobBarBGColor());  //set it's tint
mBtnAction.setBackground(newDrawable);  //apply back to button

Im Allgemeinen funktioniert es. Versucht, ViewCompataber es scheint nicht richtig zu funktionieren.

sud007
quelle
0

Sie können backgroundTint <android.support.design.button.MaterialButtonmit "com.android.support:design:28.0.0-rc01"Version verwenden

Zafer Celaloglu
quelle
0

Wenn Sie Androidx verwenden, können Sie das Problem mit Android 5.1 beheben, indem Sie sowohl ein Präfix als auch ein Präfix hinzufügen.

<style name="Button_Primary">
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:backgroundTint">@color/button_primary_selector</item>
    <item name="backgroundTint">@color/button_primary_selector</item><!--needed for android 5-->
</style>

Die Auswahl von button_primary befindet sich in einem colorOrdner mit folgendem Inhalt:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:local="http://schemas.android.com/apk/res-auto">
    <item android:state_enabled="true" android:color="@android:color/holo_blue_dark" />
    <item android:state_enabled="false" android:color="@android:color/darker_gray" />
</selector>

und wende es auf den normalen Knopf an AppCompatActivity

<Button style="@style/Button_Primary"/>
Schlau
quelle