Comment ajouter une teinte de bouton par programmation


120

Dans la nouvelle bibliothèque AppCompat, nous pouvons teinter le bouton de cette façon:

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

Comment puis-je définir la teinte du bouton par programmation dans mon code? J'essaie essentiellement d'implémenter une coloration conditionnelle du bouton en fonction de certaines entrées de l'utilisateur.


Êtes-vous sûr d'Android: backgroundTint fonctionne sur Pre-Lollipop? Je teste à la fois avec Button et ApCompatButton mais backgroundTint ne semble fonctionner que sur Lollipop.
Sharj

1
Veuillez vérifier cette réponse .
Amit Vaghela

Réponses:


162

Selon la documentation, la méthode associée android:backgroundTintest setBackgroundTintList (liste ColorStateList)

Mettre à jour

Suivez ce lien pour savoir comment créer une ressource de liste d'état des couleurs.

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

puis chargez-le en utilisant

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

contextInstanceest une instance d'unContext


en utilisant AppCompart

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

qui n'est pas une couleur, mais une ColorStateList. Comment en tirer parti?
Stephane

4
Je comprends maintenant comment le faire, mais pourquoi Android ne vous permettrait-il pas d'utiliser simplement une couleur manuellement? Pour chaque couleur de chaque bouton que j'ai, je devrai créer un XML pour un ColorStateList? Cela me semble être un gâchis
Stephane

2
setBackgroundTintList a besoin de l'API 21 même si vous l'appelez sur AppCompatButton.
Sharj

29
La bibliothèque de support AppCompat offre un assistant statique: ViewCompat.setBackgroundTintList(View, ColorStateList)qui peut être utilisé jusqu'à l'API 4. Mais cela ne fonctionne que pour les vues qui implémentent TintableBackgroundView, par exemple AppCompatButton(au lieu de l'habituel Button).
Jon Adams

1
Maintenant, utiliser ViewCompat.setBackgroundTintList(View, ColorStateList), comme @Jon Adams l'a suggéré, a encore plus de sens puisque View.setSupportButtonTintList est limité avec des RestrictToannotations. Détails ici: developer.android.com/reference/android/support/annotation/…
AlexKost

75

Vous pourriez utiliser

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

Mais je vous recommanderais d'utiliser une bibliothèque de support de teinture dessinable qui vient de sortir hier:

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

Vous pouvez en trouver plus dans ce billet de blog (voir la section "Teinture dessinable")


2
pourriez-vous fournir un code complet pour définir la teinte en utilisant la méthode ur?
M. Usman Khan

Meilleure réponse...!
Gokul Nath KP

60

On dirait que les vues ont leurs propres mécanismes pour la gestion des teintes, il vaut donc mieux mettre la liste des teintes:

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

Bien mieux l'utiliser de cette façon, vous obtenez donc une compatibilité descendante avec l'API 4!
xarlymg89

une des meilleures solutions.
Atif AbbAsi

21

Pour étendre correctement la réponse de dimsuz en fournissant une situation de code réelle, consultez l'extrait de code suivant:

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

Cette solution est pour le scénario où un dessinable est utilisé comme arrière-plan du bouton. Cela fonctionne également sur les appareils pré-Lollipop.


@TruptiNasit Heureux d'entendre ça.
Shayne3000 du

A travaillé pour moi. Je vous remercie.
wesley franks le

1
@wesleyfranks De rien. Heureux d'entendre que cela a fonctionné.
Shayne3000

7

Avez-vous essayé quelque chose comme ça?

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

notez que getResources () ne fonctionnera que dans une activité. Mais il peut également être appelé dans tous les contextes.


Vous pouvez créer un xml comme décrit ici: developer.android.com/reference/android/content/res/...
Chris K.

getColorStateList semble être obsolète.
cloudsurfin

1
setBackgroundTintList semble nécessiter le niveau d'API 21
Nashe

1
bouton. setBackgroundTintList (ContextCompat.getColorStateList (contexte, R.color.blue)); a travaillé pour moi
jesto paul


5

Vous pouvez utiliser DrawableCompat par exemple

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

5

ceci est facilement géré dans le nouveau bouton de matériau de la bibliothèque de conception de matériaux, tout d'abord, ajoutez la dépendance:

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

puis dans votre XML, utilisez ceci pour votre bouton:

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

et quand vous voulez changer la couleur, voici le code dans Kotlin, il n'est pas obsolète et il peut être utilisé avant Android 21:

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

Existe-t-il une teinte similaire pour la teinte du texte elle-même?
développeur android

vous voulez dire du texte sous forme de bouton et vous voulez changer la couleur de l'arrière-plan?
Amin Keshavarzian

4

J'ai réussi à faire fonctionner le mien en utilisant CompoundButtonCompat.setButtonTintList(button, colour).

À ma connaissance, cela fonctionne quelle que soit la version d'Android.


3

J'avais un problème similaire. Je souhaitais colorer un arrière-plan dessinable complexe pour une vue basée sur une valeur de couleur (int). J'ai réussi en utilisant le code:

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

Où couleur est une valeur int représentant la couleur requise. Cela représente le simple ColorStateList xml:

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

J'espère que cela t'aides.


2
Niveau API minimum requis 21
forsberg

ColorStateList.valueOf(ColorInt)
Eh

2

Pour ImageButton, vous pouvez utiliser:

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

setColorFilter n'est pas défini pour Buttons
Jérémy

C'est le cas pour ImageButton.
Saurabh Singh

Oh ok, je n'en savais rien. Mais OP demande Button. Pouvez-vous modifier votre réponse avec ce détail afin que je puisse supprimer mon vote défavorable?
Jérémy

2

Si vous utilisez Kotlinet Material Design, vous pouvez changer la couleur de votre MaterialButtoncomme ceci:

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

Vous pouvez l'améliorer encore mieux en créant une fonction d'extension pour votre MaterialButtonafin de rendre votre code plus lisible et votre codage un peu plus pratique:

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

Ensuite, vous pouvez utiliser votre fonction partout comme ceci:

myButton.changeColor(R.color.myColor)

1

En plus de la réponse de Shayne3000 , vous pouvez également utiliser une ressource de couleur (pas seulement une couleur int). Version 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 réponse suggérée ici ne fonctionne pas correctement sur Android 5.0 si votre liste d'états de couleurs basée sur XML fait référence à des attributs thématiques. Par exemple, j'ai une liste d'états de couleurs xml comme ceci:

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

Utiliser ceci comme arrière-planTint de xml fonctionne très bien sur Android 5.0 et tout le reste. Cependant, si j'essaie de définir cela dans un code comme celui-ci:

(Ne fais pas ça)

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

En fait, peu importe si je transmets l'activité ou le contexte du bouton à la méthode ContextCompat.getColorStateList (), ni l'un ni l'autre ne me donnera la liste d'état de couleur appropriée par rapport au thème dans lequel se trouve le bouton. En effet, l'utilisation d'attributs de thème dans les listes d'états de couleurs n'était pas prise en charge avant l'api 23 et ContextCompat ne fait rien de spécial pour les résoudre. À la place, vous devez utiliser AppCompatResources.getColorStateList () qui effectue sa propre analyse syntaxique des ressources / résolution d'attributs de thème sur les appareils <API 23.

Au lieu de cela, vous devez utiliser ceci:

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

TLDR: utilisez AppCompatResources et non -ContextCompat- si vous avez besoin de ressources thématiques résolues dans toutes les versions d'API d'Android.

Pour plus d'informations sur le sujet, consultez cet article .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.