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.

Stéphane
la source
Ê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));
Feu froid
la source
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")

dimsuz
la source
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));
tse
la source
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.

Shayne3000
la source
@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.

Chris K.
la source
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
7

voici comment le faire dans kotlin:

view.background.setTint(ContextCompat.getColor(context, textColor))
Amin Keshavarzian
la source
1
merci, cela a très bien fonctionné!
Stoica Mircea
Cela devrait être la réponse. Merci!
Andrei Vinogradov il y a
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;
}
mac229
la source
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))
Amin Keshavarzian
la source
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.

Matt Jenje
la source
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.

Montrez votre travail
la source
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
Saurabh Singh
la source
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)
Azizjon Kholmatov
la source
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
froid
la source
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 .

Matt Wolfe
la source