Come aggiungere la tinta del pulsante a livello di codice


120

Nella nuova libreria AppCompat, possiamo colorare il pulsante in questo modo:

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

Come posso impostare la tinta del pulsante a livello di codice nel mio codice? Fondamentalmente sto cercando di implementare una colorazione condizionale del pulsante basata su alcuni input dell'utente.


Sei sicuro che android: backgroundTint stia funzionando su Pre-Lollipop? Provo sia con Button che con ApCompatButton ma backgroundTint sembra funzionare solo su Lollipop.
Sharj

1
Per favore controlla questa risposta .
Amit Vaghela

Risposte:


162

Secondo la documentazione il metodo correlato a android:backgroundTintè setBackgroundTintList (elenco ColorStateList)

Aggiornare

Segui questo collegamento per sapere come creare una risorsa Elenco stato colore.

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

quindi caricarlo utilizzando

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

dove contextInstanceè un'istanza di un fileContext


utilizzando AppCompart

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

che non è un colore, ma un ColorStateList. Come sfruttarlo?
Stephane

4
Ora capisco come farlo grazie, ma perché Android non ti consente di usare solo un colore manualmente? Per ogni colore di ogni pulsante che ho, dovrò creare un xml per un ColorStateList? A me sembra uno spreco
Stephane il

2
setBackgroundTintList richiede l'API 21 anche se la chiami su AppCompatButton.
Sharj

29
La libreria di supporto AppCompat offre un helper statico: ViewCompat.setBackgroundTintList(View, ColorStateList)che può essere utilizzato fino all'API 4. Ma funziona solo per le viste che implementano TintableBackgroundView, ad esempio AppCompatButton(invece del solito Button).
Jon Adams

1
Ora, l'utilizzo ViewCompat.setBackgroundTintList(View, ColorStateList), come suggerito da @Jon Adams, ha ancora più senso poiché View.setSupportButtonTintList è limitato con l' RestrictToannotazione. Dettagli qui: developer.android.com/reference/android/support/annotation/…
AlexKost

75

Potresti usare

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

Ma ti consiglierei di utilizzare una colorazione disegnabile della libreria di supporto che è stata appena rilasciata ieri:

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

Puoi trovare ulteriori informazioni in questo post del blog (vedi la sezione "Tinte disegnabili")


2
potresti fornire il codice completo per impostare la tinta usando il tuo metodo?
M. Usman Khan

Migliore risposta...!
Gokul Nath KP

60

Sembra che le viste abbiano meccanismi propri per la gestione della tinta, quindi meglio sarà messo l'elenco delle tinte:

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

Molto meglio usarlo in questo modo, in modo da ottenere la retrocompatibilità dall'API 4!
xarlymg89

una delle migliori soluzioni.
Atif AbbAsi

21

Per estendere correttamente la risposta di dimsuz fornendo una situazione di codice reale, vedere il seguente frammento di codice:

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

Questa soluzione è per lo scenario in cui un oggetto disegnabile viene utilizzato come sfondo del pulsante. Funziona anche su dispositivi pre-Lollipop.


@TruptiNasit Sono contento di sentirlo.
Shayne3000

Ha funzionato per me. Grazie.
wesley franks

1
@wesleyfranks Sei il benvenuto. Sono contento di sentire che ha funzionato.
Shayne3000

7

Hai provato qualcosa di simile?

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

nota che getResources () funzionerà solo in un'attività. Ma può essere richiamato anche in ogni contesto.


Potresti creare un xml come descritto qui: developer.android.com/reference/android/content/res/…
Chris K.

getColorStateList sembra essere deprecato.
cloudsurfin

1
setBackgroundTintList sembra richiedere il livello API 21
Nashe

1
pulsante. setBackgroundTintList (ContextCompat.getColorStateList (context, R.color.blue)); ha funzionato per me
jesto paul


5

Puoi usare DrawableCompat es

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

5

questo è facilmente gestibile nel nuovo pulsante Material dalla libreria di material design, prima aggiungi la dipendenza:

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

quindi nel tuo XML, usa questo per il tuo pulsante:

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

e quando vuoi cambiare il colore, ecco il codice in Kotlin, non è deprecato e può essere utilizzato prima di Android 21:

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

Ce n'è uno simile per la tinta del testo stesso?
sviluppatore Android

intendi il testo come pulsante e vuoi cambiare il colore dello sfondo?
Amin Keshavarzian

4

Il modo in cui sono riuscito a far funzionare il mio è stato usando CompoundButtonCompat.setButtonTintList(button, colour).

A quanto mi risulta, funziona indipendentemente dalla versione di Android.


3

Ho avuto un problema simile. Desideravo colorare uno sfondo disegnabile complesso per una vista basata su un valore di colore (int). Ci sono riuscito usando il codice:

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

Dove color è un valore int che rappresenta il colore richiesto. Questo rappresenta il semplice xml ColorStateList:

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

Spero che questo ti aiuti.


2
Livello API minimo richiesto 21
forsberg

beh, potresti semplicemente usareColorStateList.valueOf(ColorInt)
user924

2

Per ImageButton puoi usare:

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

setColorFilter non è definito per Buttons
Jérémy

Lo è, per ImageButton.
Saurabh Singh

Oh ok, non lo sapevo. Ma OP sta chiedendo Button. Puoi modificare la tua risposta con questo dettaglio in modo che io possa rimuovere il mio voto negativo?
Jérémy

2

Se stai usando Kotline Material Design, puoi cambiare il colore del tuo in MaterialButtonquesto modo:

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

Puoi migliorarlo ancora meglio creando una funzione di estensione per il tuo MaterialButtonin modo da rendere il tuo codice più leggibile e la tua codifica un po 'più comoda:

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

Quindi, puoi usare la tua funzione ovunque in questo modo:

myButton.changeColor(R.color.myColor)

1

Oltre alla risposta di Shayne3000 puoi anche usare una risorsa colore (non solo un colore int). Versione 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

La risposta suggerita qui non funziona correttamente su Android 5.0 se l'elenco di stato del colore basato su XML fa riferimento ad attributi a tema. Ad esempio, ho un elenco di stato del colore xml in questo modo:

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

Usarlo come backgroundTint da xml funziona perfettamente su Android 5.0 e tutto il resto. Tuttavia, se provo a impostarlo in un codice come questo:

(Non farlo)

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

In realtà non importa se passo l'attività o il contesto del pulsante al metodo ContextCompat.getColorStateList (), né mi fornirà l'elenco di stato del colore corretto rispetto al tema in cui si trova il pulsante. Questo perché l'uso degli attributi del tema negli elenchi di stato dei colori non era supportato fino a quando api 23 e ContextCompat non fa nulla di speciale per risolverli. Invece è necessario utilizzare AppCompatResources.getColorStateList () che esegue la propria analisi delle risorse / risoluzione degli attributi del tema sui dispositivi <API 23.

Invece, devi usare questo:

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

TLDR: usa AppCompatResources e non -ContextCompat- se avrai bisogno di risorse a tema risolte in tutte le versioni API di Android.

Per ulteriori informazioni sull'argomento, vedere questo articolo .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.