Bouton Android standard avec une couleur différente


735

J'aimerais changer légèrement la couleur d'un bouton Android standard afin de mieux correspondre à la marque d'un client.

Le meilleur moyen que j'ai trouvé pour le faire jusqu'à présent est de changer le Buttondessinable du en dessinable situé dans res/drawable/red_button.xml:

<?xml version="1.0" encoding="utf-8"?>    
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/red_button_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/red_button_focus" />
    <item android:drawable="@drawable/red_button_rest" />
</selector>

Mais cela nécessite que je crée en fait trois dessins différents pour chaque bouton que je souhaite personnaliser (un pour le bouton au repos, un lorsqu'il est concentré et un lorsqu'il est enfoncé). Cela semble plus compliqué et non SEC que je n'en ai besoin.

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


Réponses:


724

J'ai découvert que tout cela peut être fait assez facilement dans un seul fichier. Placez quelque chose comme le code suivant dans un fichier nommé custom_button.xml, puis définissez-le background="@drawable/custom_button"dans la vue de votre bouton:

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

    <item android:state_pressed="true" >
        <shape>
            <gradient
                android:startColor="@color/yellow1"
                android:endColor="@color/yellow2"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

    <item android:state_focused="true" >
        <shape>
            <gradient
                android:endColor="@color/orange4"
                android:startColor="@color/orange5"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

    <item>        
        <shape>
            <gradient
                android:endColor="@color/blue2"
                android:startColor="@color/blue25"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
</selector>

43
Cela fonctionne bien pour la couleur d'arrière-plan - pouvez-vous définir la couleur du texte de la même manière?
Rachel

8
Cela me donne "Error: No resource found that matches the given name (at 'color' with value '@color/yellow1')" Ces références aux couleurs intégrées? semble avoir besoin d'un res / values ​​/ color.xml pour que cela fonctionne
Harry Wood

8
@HarryWood vous devez définir ces couleurs dans votre res / values ​​/ colours.xml. Alternativement, remplacez-les par "# ff0000", "# 00ff00", à des fins de test @ cfarm54 Ce fichier doit être placé dans le dossier res / drawable / custom_button.xml @emmby Merci pour l'extrait de code!
espinchi

17
Grand pointeur, merci! Notez également que pour les autres personnes qui essaient cela, l'ordre des éléments dans le sélecteur est important. Si vous placez le <item> sans filtre d'état en premier dans le fichier, il remplace le reste.
mikerowehl

9
pour que cela fonctionne, placez custom_button.xml dans votre dossier res / "drawable" - et créez un fichier res / values ​​/ colours.xml avec ce contenu: stackoverflow.com/questions/3738886/… - changez les noms de couleur dans l'un ou l'autre fichier pour le faire fonctionner
sami

308

À la suite de la réponse de Tomasz, vous pouvez également définir par programme l'ombre de l'ensemble du bouton en utilisant le mode multiplicateur PorterDuff. Cela changera la couleur du bouton plutôt que juste la teinte.

Si vous commencez avec un bouton ombré gris standard:

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

vous donnera un bouton ombré rouge,

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

vous donnera un bouton ombré 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.


2
Wow, j'ai juste essayé ça et c'est totalement fantastique. Je vous remercie! Savez-vous par hasard s'il existe un moyen de l'accomplir via xml d'une manière ou d'une autre?
emmby

4
Les gars, vérifiez-le sur HTC Desire! Ils ont différents boutons standard. Mes boutons qui utilisent ce code semblent géniaux lors de la définition d'un certain layout_width comme "40dp". Avec "wrap_content" ça va.
OneWorld

5
Confirmé, cette solution ne fonctionne pas très bien sur l'interface utilisateur de HTC Sense
emmby

19
Eclipse ne montre pas cela comme un correctif possible:import android.graphics.PorterDuff;
Someone Somewhere

2
Quelqu'un at-il eu des problèmes avec cela ne fonctionnant pas dans ICS? Cela ne semble pas fonctionner sur l'émulateur ou le téléphone pour moi ..
Stev_k

149

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 désirée.


Essayez de passer null dans la méthode setColorFilter. Je ne l'ai pas essayé mais ça devrait marcher.
Tomasz

6
@Pacerier à désactiver: button.getBackground (). ClearColorFilter ();
Stan Kurdziel

3
Je recommande de choisir une couleur à l'aide de la classe Color: developer.android.com/reference/android/graphics/Color.html
Mugen

Parfait pour les thèmes sombres! Je suppose que l'autre bonne réponse (setColorFilter (0xFFFF0000, PorterDuff.Mode.MULTIPLY)) fonctionne mieux pour les thèmes légers.
java.is.for.desktop

85

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

Il vous suffit de:

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

<style name="Facebook.Button" parent="ThemeOverlay.AppCompat">
    <item name="colorAccent">@color/com_facebook_blue</item>
</style>

Je recommande d'utiliser ThemeOverlay.AppCompatou votre principal AppThemecomme parent, pour garder le reste de vos styles.

2) Ajoutez ces deux lignes à votre buttonwidget:

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

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


Exemple de widget de bouton

<Button
    android:id="@+id/sign_in_with_facebook"
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="@string/sign_in_facebook"
    android:textColor="@android:color/white"
    android:theme="@style/Facebook.Button" />

Exemple de bouton avec une couleur personnalisée


1
Que fait cette ligne? "style =" @ style / Widget.AppCompat.Button.Colored ""
Charles Li

2
Cela m'a aidé à comprendre la différence entre le style et le thème. Je vous remercie.
rpattabi

2
La réponse acceptée est correcte mais trop ancienne. Celui-ci est une réponse simple et la plus à jour.
正宗 白 布鞋

Le problème avec cette réponse est que ce paramètre colorAccentinfluence plus que l'arrière-plan du bouton.
Blcknx

@Blcknx Quoi par exemple?
RediOne1

61

Vous pouvez maintenant utiliser de appcompat-v7 AppCompatButton avec l' backgroundTintattribut:

<android.support.v7.widget.AppCompatButton
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:backgroundTint="#ffaa00"/>

4
N'a pas fonctionné pour moi en utilisant l'espace de noms "android:". Mais cela a fonctionné lorsque j'ai utilisé l'espace de noms "app:" à la place.
David Velasquez

@DavidVelasquez Cela a également fonctionné pour moi sur Android Lollipop tandis que Android: namespace n'a rien changé. Merci pour l'aide!
Avinash Prabhakar

C'est la solution la plus simple et devrait être la réponse acceptée. Utilisation d'Android: backgroundTint fonctionne pour moi.
Ramashish Baranwal

1
Doit être à la app:backgroundTintplace de android:backgroundTintlorsque vous utilisez AppCompat.
Hafez Divandari

23

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'à présent n'était pas aussi facile à appliquer que prévu.

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

D'après ma lecture de la question d'origine, 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 mieux adaptée que les filtres de couleur si c'est votre objectif. Dans mon cas, je commence par une image png d'un concepteur d'interface utilisateur de ce à quoi le bouton est censé ressembler. Si je définit l'arrière-plan du bouton sur cette image, le retour de surbrillance par défaut est complètement perdu. Ce code remplace ce comportement par un effet d'obscurcissement programmatique.

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

J'ai extrait ceci en tant que classe distincte pour une application à plusieurs boutons - montré comme classe interne anonyme juste pour avoir l'idée.


C'était une excellente solution! Surtout le même effet que vous obtenez sur iOS par défaut, ce que les concepteurs aiment :-)
Christer Nordvik

J'ai essayé cela avec 2 boutons sur le même écran avec le même arrière-plan et l'effet s'applique aux deux boutons onTouch
Goofy

16

Si vous créez des boutons de couleur avec XML, vous pouvez rendre le code un peu plus propre en spécifiant l'état focalisé et enfoncé dans un fichier séparé et les réutiliser. Mon bouton vert ressemble à ceci:

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

    <item android:state_focused="true" android:drawable="@drawable/button_focused"/>
    <item android:state_pressed="true" android:drawable="@drawable/button_pressed"/>

    <item>
        <shape>
            <gradient android:startColor="#ff00ff00" android:endColor="#bb00ff00" android:angle="270" />
            <stroke android:width="1dp" android:color="#bb00ff00" />
            <corners android:radius="3dp" />
            <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />
        </shape>
    </item>

</selector>

1
agréable. Comment pourrait-on faire en sorte que l'état focalisé et pressé se réfère aux définitions Android standard pour les boutons?
larham1

Je suis sûr que vous ne le faites pas, car les boutons Android standard sont implémentés en tant que bitmaps à 9 correctifs.
haemish

12

La solution la plus courte qui fonctionne avec n'importe quelle version d'Android:

<Button
     app:backgroundTint="@color/my_color"

Notes / Exigences :

  • Utilisez l' app:espace de noms et non l' android:espace de noms!
  • version compatible avec l'application> 24.2.0

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

Explication : entrez la description de l'image ici


1
Fait intéressant, pour moi, cela app:backgroundTint="@color/my_color"n'a pas fonctionné. android:backgroundTint="@color/my_color"a parfaitement fonctionné.
Igor

C'est la solution la plus courte et la plus propre pour moi et c'est tout.
Marty

11

J'utilise cette approche

style.xml

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:colorPrimaryDark">#413152</item>
    <item name="android:colorPrimary">#534364</item>
    <item name="android:colorAccent">#534364</item>
    <item name="android:buttonStyle">@style/MyButtonStyle</item>
</style>

<style name="MyButtonStyle" parent="Widget.AppCompat.Button.Colored">
    <item name="android:colorButtonNormal">#534364</item>
    <item name="android:textColor">#ffffff</item>
</style>

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 c'est une bien meilleure approche que la configuration, android:backgroundcar je ne perdrai pas l'effet d'entraînement que Google fournit.


8

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

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


8

Utilisez-le de cette façon:

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

4

En cours d' <Button>utilisation android:background="#33b5e5". ou mieuxandroid:background="@color/navig_button"


3

La bibliothèque de composants DroidUX dispose d'un ColorButtonwidget dont la couleur peut être modifiée facilement, à la fois via la définition xml et par programme au moment de l'exécution, de sorte que vous pouvez même laisser l'utilisateur définir la couleur / le thème du bouton si votre application le permet.


3

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


2

Vous pouvez définir le thème de votre bouton sur ce

<style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored">
 <item name="colorButtonNormal">@color/HEXColor</item>
 <item name="android:textColor">@color/HEXColor</item>
</style>

1

Un moyen simple consiste à simplement définir une classe Button personnalisée qui accepte toutes les propriétés que vous souhaitez comme le rayon, le dégradé, la couleur pressée, la couleur normale, etc. 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 enfoncé

entrez la description de l'image ici


0

La façon dont je fais un bouton de style différent qui fonctionne assez bien est de sous-classer l'objet 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.AttributeSet;
import android.widget.Button;

public class DimmableButton extends Button {

    public DimmableButton(Context context) {
        super(context);
    }

    public DimmableButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DimmableButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @SuppressWarnings("deprecation")
    @Override
    public void setBackgroundDrawable(Drawable d) {
        // Replace the original background drawable (e.g. 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 (e.g. 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;
        }
    }

}

0

values ​​\ styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

<style name="RedAccentButton" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorAccent">#ff0000</item>
</style>

puis:

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="text" />

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:enabled="false"
    android:text="text" />

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="text"
    android:theme="@style/RedAccentButton" />

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:enabled="false"
    android:text="text"
    android:theme="@style/RedAccentButton" />

résultat


0

Selon les directives de conception des matériaux, vous devez utiliser le style comme le code ci-dessous

<style name="MyButton" parent="Theme.AppCompat.Light>
    <item name="colorControlHighlight">#F36F21</item>
    <item name="colorControlHighlight">#FF8D00</item>
</style>

et dans la mise en page, ajoutez cette propriété à votre bouton

    android:theme="@style/MyButton"

0

C'est simple .. ajoutez cette dépendance dans votre projet et créez un bouton avec 1. N'importe quelle forme 2. N'importe quelle couleur 3. N'importe quelle bordure 4. Avec des effets de matière

https://github.com/manojbhadane/QButton

<com.manojbhadane.QButton
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="OK"
       app:qb_backgroundColor="@color/green"
       app:qb_radius="100"
       app:qb_strokeColor="@color/darkGreen"
       app:qb_strokeWidth="5" />
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.