Bouton Android standard avec une couleur différente

Je voudrais changer légèrement la couleur d’un bouton Android standard afin de mieux correspondre à la marque d’un client.

La meilleure façon de le faire jusqu’à présent est de changer le dessin du Button le dessin suivant situé dans res/drawable/red_button.xml :

       

Mais pour cela, il faut que je crée trois tirables différents pour chaque bouton que je souhaite personnaliser (un pour le bouton au repos, l’autre pour le bouton et l’autre pour le bouton). Cela semble plus compliqué et non-sec que ce dont j’ai besoin.

Tout ce que je veux vraiment faire, c’est appliquer une sorte de transformation de couleur au bouton. Y a-t-il un moyen plus facile de changer la couleur d’un bouton que je ne le fais?

J’ai découvert que cela pouvait être fait dans un seul fichier assez facilement. Mettez quelque chose comme le code suivant dans un fichier nommé custom_button.xml , puis définissez background="@drawable/custom_button" dans votre vue bouton:

                            

Suite à la réponse de Tomasz, vous pouvez également définir par programmation la nuance de la totalité du bouton en utilisant le mode multiplicateur PorterDuff. Cela changera la couleur du bouton plutôt que la teinte.

Si vous commencez avec un bouton gris ombré standard:

 button.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY); 

vous donnera un bouton rouge ombré,

 button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY); 

vous donnera un bouton vert, etc., où la première valeur est la couleur au format hexadécimal.

Cela fonctionne en multipliant la valeur de couleur actuelle du bouton par votre valeur de couleur. Je suis sûr que vous pouvez faire beaucoup plus avec ces modes.

Mike, vous pourriez être intéressé par les filtres de couleur.

Un exemple:

 button.getBackground().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFFAA0000)); 

Essayez ceci pour obtenir la couleur que vous voulez.

C’est ma solution qui fonctionne parfaitement à partir de l’API 15 . Cette solution conserve tous les effets de clics sur les boutons par défaut, comme le matériel RippleEffect . Je ne l’ai pas testé sur des API inférieures, mais cela devrait fonctionner.

Tout ce que vous devez faire, c’est:

1) Créez un style qui ne change que la colorAccent :

  

Je recommande d’utiliser ThemeOverlay.AppCompat ou votre AppTheme principal en AppTheme que parent, pour conserver le rest de vos styles.

2) Ajoutez ces deux lignes à votre widget button :

 style="@style/Widget.AppCompat.Button.Colored" android:theme="@style/Facebook.Button" 

Parfois, votre nouveau colorAccent pas dans Android Studio Preview, mais lorsque vous lancez votre application sur le téléphone, la couleur est modifiée.


Widget bouton échantillon

  

Bouton d'échantillon avec couleur personnalisée

Vous pouvez maintenant également utiliser AppCompatButton de appcompat-v7 avec l’atsortingbut backgroundTint :

  

J’aime la suggestion de filtre de couleur dans les réponses précédentes de @conjugatedirection et @Tomasz; Cependant, j’ai trouvé que le code fourni jusqu’ici n’était pas aussi facilement appliqué que prévu.

Tout d’abord, il n’a pas été mentionné appliquer et effacer le filtre de couleur. Il est possible qu’il y ait d’autres bons endroits pour le faire, mais ce qui m’est venu à l’esprit, c’était un OnTouchListener .

De ma lecture de la question initiale, la solution idéale serait celle qui n’implique aucune image. La réponse acceptée en utilisant custom_button.xml de @emmby est probablement plus adaptée que les filtres de couleur si c’est votre objective. Dans mon cas, je commence avec une image png d’un concepteur d’interface utilisateur de ce à quoi le bouton est censé ressembler. Si je règle l’arrière-plan du bouton sur cette image, le retour d’informations par défaut est complètement perdu. Ce code remplace ce comportement par un effet d’assombrissement par programmation.

 button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 0x6D6D6D sets how much to darken - tweak as desired setColorFilter(v, 0x6D6D6D); break; // remove the filter when moving off the button // the same way a selector implementation would case MotionEvent.ACTION_MOVE: Rect r = new Rect(); v.getLocalVisibleRect(r); if (!r.contains((int) event.getX(), (int) event.getY())) { setColorFilter(v, null); } break; case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: setColorFilter(v, null); break; } return false; } private void setColorFilter(View v, Integer filter) { if (filter == null) v.getBackground().clearColorFilter(); else { // To lighten instead of darken, try this: // LightingColorFilter lighten = new LightingColorFilter(0xFFFFFF, filter); LightingColorFilter darken = new LightingColorFilter(filter, 0x000000); v.getBackground().setColorFilter(darken); } // required on Android 2.3.7 for filter change to take effect (but not on 4.0.4) v.getBackground().invalidateSelf(); } }); 

Je l’ai extrait en tant que classe distincte pour application à plusieurs boutons – montré comme classe interne anonyme juste pour avoir l’idée.

Si vous créez des boutons de couleur avec XML, vous pouvez rendre le code un peu plus net en spécifiant l’état mis au point et pressé dans un fichier séparé et en les réutilisant. Mon bouton vert ressemble à ceci:

              

La solution la plus courte qui fonctionne avec toute version Android:

 

Notes / Exigences :

  • Utilisez l' app: namespace et non l' android: namespace!
  • version appcompat> 24.2.0

    dépendances {comstackr 'com.android.support:appcompat-v7:25.3.1'}

Explication : entrer la description de l'image ici

J’utilise cette approche

style.xml

    

Comme vous pouvez le voir ci-dessus, j’utilise un style personnalisé pour mon bouton. La couleur du bouton correspond à la couleur d’accent. Je trouve que cette approche est bien meilleure que la configuration de android:background car je ne perdrai pas l’effet d’effet de Google.

Il existe un moyen beaucoup plus facile maintenant: android-holo-colors.com

Cela vous permettra de changer facilement les couleurs de tous les holo drawables (boutons, spinners, …). Vous sélectionnez la couleur, puis téléchargez un fichier zip contenant des tirables pour toutes les résolutions.

Utilisez-le de cette manière:

 buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY); 

Dans utilisez android:background="#33b5e5" . ou mieux android:background="@color/navig_button"

La bibliothèque de composants DroidUX possède un widget ColorButton dont la couleur peut être facilement modifiée, à la fois par définition XML et par programmation lors de l’exécution. Vous pouvez donc laisser l’utilisateur définir la couleur / le thème du bouton si votre application le permet.

Vous pouvez également utiliser cet outil en ligne pour personnaliser votre bouton http://angrytools.com/android/button/ et utiliser android:background="@drawable/custom_btn" pour définir le bouton personnalisé dans votre mise en page.

Vous pouvez définir le thème de votre bouton à cette

  

Une méthode simple consiste simplement à définir une classe Button personnalisée qui accepte toutes les propriétés souhaitées (rayon, dégradé, couleur pressée, couleur normale, etc.), puis à utiliser uniquement dans vos mises en page XML au lieu de configurer l’arrière-plan avec XML. Un échantillon est ici

Ceci est extrêmement utile si vous avez beaucoup de boutons avec les mêmes propriétés comme le rayon, la couleur sélectionnée, etc. Vous pouvez personnaliser votre bouton hérité pour gérer ces propriétés supplémentaires.

Résultat (aucun sélecteur d’arrière-plan n’a été utilisé).

Bouton normal

Image normale

Bouton pressé

entrer la description de l'image ici

La façon dont je fais un bouton de style différent qui fonctionne assez bien est de sous-classer l’object Button et d’appliquer un filtre de couleur. Cela gère également les états activés et désactivés en appliquant un alpha au bouton.

 import android.annotation.TargetApi; import android.content.Context; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.LightingColorFilter; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Build; import android.util.AtsortingbuteSet; import android.widget.Button; public class DimmableButton extends Button { public DimmableButton(Context context) { super(context); } public DimmableButton(Context context, AtsortingbuteSet attrs) { super(context, attrs); } public DimmableButton(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); } @SuppressWarnings("deprecation") @Override public void setBackgroundDrawable(Drawable d) { // Replace the original background drawable (eg image) with a LayerDrawable that // contains the original drawable. DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d); super.setBackgroundDrawable(layer); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void setBackground(Drawable d) { // Replace the original background drawable (eg image) with a LayerDrawable that // contains the original drawable. DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d); super.setBackground(layer); } /** * The stateful LayerDrawable used by this button. */ protected class DimmableButtonBackgroundDrawable extends LayerDrawable { // The color filter to apply when the button is pressed protected ColorFilter _pressedFilter = new LightingColorFilter(Color.LTGRAY, 1); // Alpha value when the button is disabled protected int _disabledAlpha = 100; // Alpha value when the button is enabled protected int _fullAlpha = 255; public DimmableButtonBackgroundDrawable(Drawable d) { super(new Drawable[] { d }); } @Override protected boolean onStateChange(int[] states) { boolean enabled = false; boolean pressed = false; for (int state : states) { if (state == android.R.attr.state_enabled) enabled = true; else if (state == android.R.attr.state_pressed) pressed = true; } mutate(); if (enabled && pressed) { setColorFilter(_pressedFilter); } else if (!enabled) { setColorFilter(null); setAlpha(_disabledAlpha); } else { setColorFilter(null); setAlpha(_fullAlpha); } invalidateSelf(); return super.onStateChange(states); } @Override public boolean isStateful() { return true; } } } 

values ​​\ styles.xml

   

puis:

     

résultat