Jak programowo dodać odcień przycisków


120

W nowej bibliotece AppCompat możemy zabarwić przycisk w ten sposób:

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/follow"
    android:id="@+id/button_follow"
    android:backgroundTint="@color/blue_100"
    />

Jak mogę programowo ustawić odcień przycisku w moim kodzie? Zasadniczo próbuję zaimplementować warunkowe kolorowanie przycisku na podstawie danych wejściowych użytkownika.


Czy na pewno Android: backgroundTint działa na Pre-Lollipop? Testuję zarówno z Button, jak i ApCompatButton, ale backgroundTint wydaje się działać tylko na Lollipop.
Sharj

1
Proszę sprawdzić tę odpowiedź .
Amit Vaghela

Odpowiedzi:


162

Zgodnie z dokumentacją powiązaną metodą android:backgroundTintjest setBackgroundTintList (lista ColorStateList)

Aktualizacja

Skorzystaj z tego łącza, aby dowiedzieć się, jak utworzyć zasób listy stanów kolorów.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:color="#your_color_here" />
</selector>

następnie załaduj go za pomocą

setBackgroundTintList(contextInstance.getResources().getColorStateList(R.color.your_xml_name));

gdzie contextInstancejest wystąpieniemContext


przy użyciu AppCompart

btnTag.setSupportButtonTintList(ContextCompat.getColorStateList(Activity.this, R.color.colorPrimary));

który nie jest kolorem, ale ColorStateList. Jak to wykorzystać?
Stephane

4
Teraz rozumiem, jak to zrobić, ale dlaczego Android miałby nie pozwolić na ręczne użycie koloru? Dla każdego koloru każdego przycisku, który mam, będę musiał utworzyć xml dla ColorStateList? Wydaje mi się, że to strata
Stephane

2
setBackgroundTintList wymaga interfejsu API 21, nawet jeśli wywołasz go w AppCompatButton.
Sharj

29
Biblioteka wsparcia AppCompat oferuje statyczny pomocnik: ViewCompat.setBackgroundTintList(View, ColorStateList)może być używany aż do API 4. Ale działa tylko dla widoków, które implementują TintableBackgroundViewna przykład AppCompatButton(zamiast zwykłych Button).
Jon Adams,

1
Teraz używanie ViewCompat.setBackgroundTintList(View, ColorStateList), jak zasugerował @Jon Adams, ma jeszcze większy sens, ponieważ View.setSupportButtonTintList jest ograniczone do RestrictToadnotacji. Szczegóły tutaj: developer.android.com/reference/android/support/annotation/…
AlexKost

75

Możesz użyć

button.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(R.id.blue_100)));

Ale poleciłbym ci skorzystanie z biblioteki obsługi barwienia do rysowania, która właśnie została wydana wczoraj:

Drawable drawable = ...;

// Wrap the drawable so that future tinting calls work
// on pre-v21 devices. Always use the returned drawable.
drawable = DrawableCompat.wrap(drawable);

// We can now set a tint
DrawableCompat.setTint(drawable, Color.RED);
// ...or a tint list
DrawableCompat.setTintList(drawable, myColorStateList);
// ...and a different tint mode
DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_OVER);

Więcej informacji można znaleźć w tym poście na blogu (patrz sekcja „Barwienie do rysowania”)


2
może u podać pełny kod, aby ustawić odcień przy użyciu metody ur?
M. Usman Khan

Najlepsza odpowiedź...!
Gokul Nath KP

60

Wygląda na to, że widoki mają własną mechanikę zarządzania odcieniami, więc lepiej będzie umieścić listę odcieni:

ViewCompat.setBackgroundTintList(
    editText, 
    ColorStateList.valueOf(errorColor));

Znacznie lepiej, używając tego w ten sposób, dzięki czemu uzyskasz kompatybilność wsteczną z API 4!
xarlymg89

jedno z najlepszych rozwiązań.
Atif AbbAsi

21

W poprawnym rozszerzeniu odpowiedzi dimsuza przez podanie rzeczywistej sytuacji w kodzie, zobacz następujący fragment kodu:

    Drawable buttonDrawable = button.getBackground();
    buttonDrawable = DrawableCompat.wrap(buttonDrawable);
    //the color is a direct color int and not a color resource
    DrawableCompat.setTint(buttonDrawable, Color.RED);
    button.setBackground(buttonDrawable);

To rozwiązanie jest dla scenariusza, w którym element rysunkowy jest używany jako tło przycisku. Działa również na urządzeniach sprzed wersji Lollipop.


@TruptiNasit Miło to słyszeć.
Shayne3000

Pracował dla mnie. Dziękuję Ci.
wesley franks

1
@wesleyfranks Nie ma za co. Miło słyszeć, że zadziałało.
Shayne3000,

7

Czy próbowałeś czegoś takiego?

button.setBackgroundTintList(getResources().getColorStateList(R.id.blue_100));

pamiętaj, że getResources () będzie działać tylko w działaniu. Ale można go również wywołać w każdym kontekście.


Możesz utworzyć plik XML zgodnie z opisem tutaj: developer.android.com/reference/android/content/res/…
Chris K.

getColorStateList wydaje się być przestarzałe.
cloudsurfin

1
setBackgroundTintList wydaje się wymagać poziomu API 21
Nashe

1
przycisk. setBackgroundTintList (ContextCompat.getColorStateList (kontekst, R.color.blue)); pracował dla mnie
jesto paul


5

Możesz użyć DrawableCompat np

public static Drawable setTint(Drawable drawable, int color) {
    final Drawable newDrawable = DrawableCompat.wrap(drawable);
    DrawableCompat.setTint(newDrawable, color);
    return newDrawable;
}

5

można to łatwo obsłużyć w nowym przycisku Material z biblioteki Material Design, najpierw dodaj zależność:

implementation 'com.google.android.material:material:1.1.0-alpha07'

następnie w swoim kodzie XML użyj tego jako przycisku:

<com.google.android.material.button.MaterialButton
    android:id="@+id/accept"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/i_accept"
    android:textSize="18sp"
    app:backgroundTint="@color/grayBackground_500" />

a jeśli chcesz zmienić kolor, oto kod w Kotlinie, nie jest przestarzały i można go używać przed Androidem 21:

accept.backgroundTintList = ColorStateList.valueOf(ResourcesCompat.getColor(resources, 
R.color.colorPrimary, theme))

Czy istnieje podobny odcień samego tekstu?
programista Androida

masz na myśli tekst jako przycisk i chcesz zmienić kolor tła?
Amin Keshavarzian,

4

Mój sposób, w jaki udało mi się zmusić do pracy, polegał na użyciu CompoundButtonCompat.setButtonTintList(button, colour).

W moim rozumieniu działa to niezależnie od wersji Androida.


3

Miałem podobny problem. Chciałem pokolorować złożone, możliwe do rysowania tło dla widoku na podstawie wartości koloru (int). Udało mi się, używając kodu:

ColorStateList csl = new ColorStateList(new int[][]{{}}, new int[]{color});
textView.setBackgroundTintList(csl);

Gdzie kolor jest wartością int reprezentującą wymagany kolor. To reprezentuje prostą xml ColorStateList:

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:color="color here"/>
</selector>

Mam nadzieję że to pomoże.


2
Minimalny wymagany poziom API 21
forsberg

cóż, możesz po prostu użyćColorStateList.valueOf(ColorInt)
user924,

2

W przypadku ImageButton możesz użyć:

favoriteImageButton.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint

setColorFilter nie jest zdefiniowany dla Buttons
Jérémy

To jest dla ImageButton.
Saurabh Singh

O ok, nie wiedziałem o tym. Ale OP prosi o Button. Czy możesz edytować swoją odpowiedź, podając te szczegóły, abym mógł usunąć mój głos przeciw?
Jérémy

2

Jeśli używasz Kotlini Material Design, możesz zmienić kolor swojego w MaterialButtonten sposób:

myButton.background.setTintList(ContextCompat.getColorStateList(context, R.color.myColor))

Możesz to ulepszyć jeszcze lepiej, tworząc funkcję rozszerzenia dla swojego MaterialButtonkodu, aby kod był bardziej czytelny, a kodowanie trochę wygodniejsze:

fun MaterialButton.changeColor(color: Int) {
    this.background.setTintList(ContextCompat.getColorStateList(context, color))
}

Następnie możesz używać swojej funkcji wszędzie w ten sposób:

myButton.changeColor(R.color.myColor)

1

Oprócz odpowiedzi Shayne3000 możesz również użyć zasobu koloru (nie tylko int color). Wersja Kotlin :

var indicatorViewDrawable = itemHolder.indicatorView.background
indicatorViewDrawable = DrawableCompat.wrap(indicatorViewDrawable)
val color = ResourcesCompat.getColor(context.resources, R.color.AppGreenColor, null) // get your color from resources
DrawableCompat.setTint(indicatorViewDrawable, color)
itemHolder.indicatorView.background = indicatorViewDrawable

0

Sugerowana odpowiedź tutaj nie działa poprawnie w systemie Android 5.0, jeśli lista stanów kolorów oparta na XML odwołuje się do atrybutów tematycznych. Na przykład mam listę stanów kolorów XML, taką jak ta:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="?colorPrimary" android:state_enabled="true"/>
    <item android:alpha="0.12" android:color="?attr/colorOnSurface"/>
</selector>

Używanie tego jako mojego backgroundTint z xml działa dobrze na Androidzie 5.0 i wszystkim innym. Jeśli jednak spróbuję ustawić to w kodzie w ten sposób:

(Nie rób tego)

myButton.setSupportButtonTintList(ContextCompat.getColorStateList(myButton.getContext(), R.color.btn_tint_primary));

Właściwie nie ma znaczenia, czy przekażę Activity lub kontekst przycisku do metody ContextCompat.getColorStateList (), ani nie poda mi właściwej listy stanów kolorów w odniesieniu do motywu, w którym znajduje się przycisk. Dzieje się tak, ponieważ używanie atrybutów motywu na listach stanu kolorów nie było obsługiwane przed api 23, a ContextCompat nie robi nic specjalnego, aby je rozwiązać. Zamiast tego należy użyć AppCompatResources.getColorStateList (), która wykonuje własne analizowanie zasobów / rozpoznawanie atrybutów motywu na urządzeniach <API 23.

Zamiast tego musisz użyć tego:

myButton.setSupportBackgroundTintList(AppCompatResources.getColorStateList(myButton.getContext(), R.color.btn_tint_primary));

TLDR: użyj AppCompatResources, a nie -ContextCompat-, jeśli potrzebujesz rozwiązanych zasobów tematycznych we wszystkich wersjach interfejsu API Androida.

Więcej informacji na ten temat znajdziesz w tym artykule .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.