Changer la couleur «on» d'un commutateur

156

J'utilise un contrôle Switch standard avec le thème holo.light dans une application ICS.

Je souhaite changer la couleur en surbrillance ou en état du bouton bascule du bleu clair standard au vert.

Cela devrait être facile, mais je n'arrive pas à trouver comment le faire.

JamesSugrue
la source
Je ne vois pas vraiment d'autre moyen que de copier les ressources pertinentes de la plate-forme (sélecteur et fichiers * .png) et de modifier l'état «on» dessiné. N'oubliez pas de pointer Switchvers ce sélecteur personnalisé par la suite.
MH.

Réponses:

101

À partir de maintenant, il est préférable d'utiliser SwitchCompat à partir de la bibliothèque AppCompat.v7. Vous pouvez ensuite utiliser un style simple pour changer la couleur de vos composants.

values/themes.xml:

<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">@color/my_awesome_color</item>

    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">@color/my_awesome_darker_color</item>

    <!-- colorAccent is used as the default value for colorControlActivated,
         which is used to tint widgets -->
    <item name="colorAccent">@color/accent</item>

    <!-- You can also set colorControlNormal, colorControlActivated
         colorControlHighlight, and colorSwitchThumbNormal. -->

</style>

ref: Blog des développeurs Android

MODIFIER :

La manière dont il doit être correctement appliqué est à travers android:theme="@style/Theme.MyTheme" et cela peut également être appliqué aux styles parents tels que EditTexts, RadioButtons, Switches, CheckBoxes et ProgressBars:

<style name="My.Widget.ProgressBar" parent="Widget.AppCompat.ProgressBar">

<style name="My.Widget.Checkbox" parent="Widget.AppCompat.CompoundButton.CheckBox">
SubChord
la source
1
Bien que non applicable à l'époque, cela devrait être la réponse acceptée!
Andrew Gallasch
Ont changé cela pour la réponse acceptée, car il semble l'approche la plus «moderne» de cette question.
JamesSugrue
1
J'ai essayé tous ceux-ci et aucun d'entre eux n'a changé la couleur de l'état "on" pour mon commutateur.
Adam Johns
31
«on» est colorAccent, «off» est colorSwitchThumbNormal. Si vous utilisez le AppCompatthème, vous devez utiliser SwitchCompatplutôt que Switch. Si vous utilisez SDK 23+, vous pouvez utiliser android:thumbTintet android:thumbTintModeavec un ColorStateList.
Tom
1
@Tom plz répondra est-ce que ces choses 'android: thumbTint' fonctionneront sur les appareils <23
Shirish Herwade
269

En retard pour faire la fête mais c'est comme ça que j'ai fait

Style

 <style name="SCBSwitch" parent="Theme.AppCompat.Light">
        <!-- active thumb & track color (30% transparency) -->
        <item name="colorControlActivated">#46bdbf</item>

        <!-- inactive thumb color -->
        <item name="colorSwitchThumbNormal">#f1f1f1
        </item>

        <!-- inactive track color (30% transparency) -->
        <item name="android:colorForeground">#42221f1f
        </item>
    </style>

Couleurs

entrez la description de l'image ici

Disposition

<android.support.v7.widget.SwitchCompat
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:checked="false"
    android:theme="@style/SCBSwitch" />

Résultat

Voir le changement de couleurs pour activer et désactiver le commutateur

entrez la description de l'image ici

Hitesh Sahu
la source
14
@MaksimKniazev Vous devez utiliser SwitchCompat;)
Ovi Trif
1
Bon, sauf pour colorControlActivated - il ne définit pas la couleur de la piste, seulement la couleur du pouce.
Pointer Null
1
voici une solution pour Switch et SwitchCompat: stackoverflow.com/a/47036089/5869630
roghayeh hosseini
Les balises <style> devaient être écrites sous res >> values ​​>> styles.xml et sur la page XML pour <Switch ...> vous ne devez ajouter que la ligne appelée: android: theme = "@ style / SCBSwitch et mes couleurs sont : colorControlActivated "> # ff0000 et colorSwitchThumbNormal"> # 00ff00 et android: colorForeground "> # 00ff00
Bay
@OviTrif Génial! Il est impressionnant de constater à quel point il est difficile de trouver une information simple comme celle-là. Beaucoup de réponses que j'ai lues, et personne n'a donné de réponse valable jusqu'à présent. Finalement!
jairhumberto
49

Cela fonctionne pour moi (nécessite Android 4.1):

Switch switchInput = new Switch(this);
int colorOn = 0xFF323E46;
int colorOff = 0xFF666666;
int colorDisabled = 0xFF333333;
StateListDrawable thumbStates = new StateListDrawable();
thumbStates.addState(new int[]{android.R.attr.state_checked}, new ColorDrawable(colorOn));
thumbStates.addState(new int[]{-android.R.attr.state_enabled}, new ColorDrawable(colorDisabled));
thumbStates.addState(new int[]{}, new ColorDrawable(colorOff)); // this one has to come last
switchInput.setThumbDrawable(thumbStates);

Notez que l'état "par défaut" doit être ajouté en dernier, comme indiqué ici.

Le seul problème que je vois est que le "pouce" du commutateur apparaît maintenant plus grand que l'arrière-plan ou "piste" du commutateur. Je pense que c'est parce que j'utilise toujours l'image de piste par défaut, qui a un espace vide autour d'elle. Cependant, lorsque j'ai essayé de personnaliser l'image de la piste à l'aide de cette technique, mon commutateur semblait avoir une hauteur de 1 pixel avec juste un ruban du texte d'activation / désactivation apparaissant. Il doit y avoir une solution pour ça, mais je ne l'ai pas encore trouvée ...

Mise à jour pour Android 5

Sous Android 5, le code ci-dessus fait disparaître complètement le commutateur. Nous devrions pouvoir utiliser la nouvelle méthode setButtonTintList , mais cela semble être ignoré pour les commutateurs. Mais cela fonctionne:

ColorStateList buttonStates = new ColorStateList(
        new int[][]{
                new int[]{-android.R.attr.state_enabled},
                new int[]{android.R.attr.state_checked},
                new int[]{}
        },
        new int[]{
                Color.BLUE,
                Color.RED,
                Color.GREEN
        }
);
switchInput.getThumbDrawable().setTintList(buttonStates);
switchInput.getTrackDrawable().setTintList(buttonStates);

Mise à jour pour Android 6-7

Comme l'a déclaré Cheruby dans les commentaires, nous pouvons utiliser le nouveau setThumbTintListet cela a fonctionné comme prévu pour moi. Nous pouvons également utiliser setTrackTintList, mais cela applique la couleur comme un mélange, avec un résultat plus sombre que prévu dans les thèmes de couleurs sombres et plus clair que prévu dans les thèmes de couleurs claires, parfois au point d'être invisible. Dans Android 7, j'ai pu minimiser ce changement en remplaçant le mode de teinte de la piste , mais je ne pouvais pas obtenir de résultats décents avec Android 6. Vous devrez peut-être définir des couleurs supplémentaires qui compensent le mélange. (Avez-vous déjà eu le sentiment que Google ne veut pas que nous personnalisions l'apparence de nos applications?)

ColorStateList thumbStates = new ColorStateList(
        new int[][]{
                new int[]{-android.R.attr.state_enabled},
                new int[]{android.R.attr.state_checked},
                new int[]{}
        },
        new int[]{
                Color.BLUE,
                Color.RED,
                Color.GREEN
        }
);
switchInput.setThumbTintList(thumbStates);
if (Build.VERSION.SDK_INT >= 24) {
    ColorStateList trackStates = new ColorStateList(
            new int[][]{
                    new int[]{-android.R.attr.state_enabled},
                    new int[]{}
            },
            new int[]{
                    Color.GRAY,
                    Color.LTGRAY
            }
    );
    switchInput.setTrackTintList(trackStates);
    switchInput.setTrackTintMode(PorterDuff.Mode.OVERLAY);
}
arlomedia
la source
J'utilise l'approche getThumbDrawable / getTrackDrawable pour créer un commutateur où les deux états ont la même couleur - en d'autres termes, le commutateur n'active / ne désactive pas quelque chose, mais est utilisé pour un choix entre deux alternatives.
Natix le
4
Vous avez que DrawableCompat.setTintList lui permettra de fonctionner sur les appareils précédents. J'appelle: DrawableCompat.setTintList (switchCompat.getThumbDrawable (), foregroundState);
Alexey
Veuillez modifier la réponse pour inclure la solution DrawableCompat. Cela fonctionne parfaitement!
Dmytro Karataiev
API 23+: switchInput.setThumbTintList(buttonStates); fonctionne également pour Nougat. API 21-22: utilisez DrawableCompat comme suggéré par @Alexey. Le switchInput.setButtonTintList(buttonStates);n'a pas fonctionné pour moi, il n'a pas la couleur des états pour mon commutateur. API ci-dessous 21: switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); Celles - ci ont fonctionné pour moi. J'ai également travaillé avec Xamarin, alors traduisez-les en C # dans les moteurs de rendu Android si vous utilisez Xamarin.Forms.
Cheruby
37

Pour modifier le style de commutateur sans utiliser style.xml ou code Java, vous pouvez personnaliser le commutateur en XML de disposition:

<Switch
        android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:thumbTint="@color/blue"
        android:trackTint="@color/white"
        android:checked="true"
        android:layout_height="wrap_content" />

C'est l'attribut android: thumbTint et android: trackTint qui vous ont permis de personnaliser la couleur

Voici le résultat visuel de ce XML:

entrez la description de l'image ici

Kevin ABRIOUX
la source
17
Cela change la couleur du pouce, qu'il soit activé ou désactivé.
développeur android
1
"L'attribut thumbTint n'est utilisé que dans l'API de niveau 21 et supérieur"
norbDEV
6
@norbDEV utilise app: thumbTint et app: trackTint avec SwitchCompat de la bibliothèque AppCompat.v7 pour un niveau d'API inférieur.
David Darias
Cela fonctionne, mais que se passe-t-il si vous souhaitez changer la couleur du pouce, selon qu'elle est activée ou désactivée?
TavernSenses
2
Si vous souhaitez utiliser thumbTint en dessous de 21, utilisez app:thumbTintau lieu de android:thumbTintet changez switchavecSwitchCompat
Kavita_p
33

Créez un commutateur personnalisé et remplacez l'ensemble Vérifié pour changer de couleur:

  public class SwitchPlus extends Switch {

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

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

    public SwitchPlus(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setChecked(boolean checked) {
        super.setChecked(checked);
        changeColor(checked);
    }

    private void changeColor(boolean isChecked) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            int thumbColor;
            int trackColor;

            if(isChecked) {
                thumbColor = Color.argb(255, 253, 153, 0);
                trackColor = thumbColor;
            } else {
                thumbColor = Color.argb(255, 236, 236, 236);
                trackColor = Color.argb(255, 0, 0, 0);
            }

            try {
                getThumbDrawable().setColorFilter(thumbColor, PorterDuff.Mode.MULTIPLY);
                getTrackDrawable().setColorFilter(trackColor, PorterDuff.Mode.MULTIPLY);
            }
            catch (NullPointerException e) {
                e.printStackTrace();
            }
        }
    }
}
francisco_ssb
la source
2
Le premier article qui m'a aidé à obtenir une couleur personnalisée pour le commutateur de matériau sans utiliser de style ou de thèmes. Merci !
Mackovich
1
Agréable. J'avais déjà mon propre Switch personnalisé, donc je n'ai eu qu'à remplacer la méthode setChecked et tous ont automatiquement changé leurs couleurs. Merci de l'Espagne.
Julio
22

Bien que la réponse de SubChord soit correcte, elle ne répond pas vraiment à la question de savoir comment définir la couleur "on" sans affecter également les autres widgets. Pour ce faire, utilisez un ThemeOverlaydans styles.xml:

<style name="ToggleSwitchTheme" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorAccent">@color/green_bright</item>
</style>

Et référencez-le dans votre commutateur:

<android.support.v7.widget.SwitchCompat
  android:theme="@style/ToggleSwitchTheme" ... />

Ce faisant, il affectera UNIQUEMENT la couleur des vues auxquelles vous souhaitez l'appliquer.

Greg Ennis
la source
Pour une raison quelconque, j'ai également dû définir "colorControlActivated" sur la même valeur, mais sur POC, il suffisait d'utiliser "colorAccent". Comment venir?
développeur android
22
<androidx.appcompat.widget.SwitchCompat
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:thumbTint="@color/white"
                app:trackTint="@drawable/checker_track"/>

Et à l'intérieur de checker_track.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/lightish_blue" android:state_checked="true"/>
    <item android:color="@color/hint" android:state_checked="false"/>
</selector>
wingear
la source
thumbTints'applique uniquement à l'API Android 21 et versions ultérieures. Comment si je veux changer la couleur sous Android 21?
Giovanka Bisano le
developer.android.com/reference/android/support/v7/widget/… SwitchCompat est rétrocompatible avec l'API 7 et les
versions ultérieures
1
Nous sommes en 2020. Je me demande vraiment où dans le monde les gens utilisent encore Android 21 et moins?
zeeshan
18

Je l'ai résolu en mettant à jour le filtre de couleur lorsque l'état du commutateur était changé ...

public void bind(DetailItem item) {
    switchColor(item.toggle);
    listSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                switchColor(b);
        }
    });
}

private void switchColor(boolean checked) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        listSwitch.getThumbDrawable().setColorFilter(checked ? Color.BLACK : Color.WHITE, PorterDuff.Mode.MULTIPLY);
        listSwitch.getTrackDrawable().setColorFilter(!checked ? Color.BLACK : Color.WHITE, PorterDuff.Mode.MULTIPLY);
    }
}
MCR
la source
13

Peut-être que c'est un peu tard, mais pour les boutons de commutation, le bouton toogle n'est pas la réponse, vous devez changer le dessinable dans le paramètre xml du commutateur:

 android:thumb="your drawable here"
Golgorz
la source
9

rendre "newthumb.xml" dessinable

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/Green" android:state_checked="true"/>
    <item android:color="@color/Red" android:state_checked="false"/>
</selector>

et rendre "newtrack.xml" dessinable

<selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@color/black" android:state_checked="true"/>
        <item android:color="@color/white" android:state_checked="false"/>
    </selector>

et ajoutez-le dans Switch:

<Switch
        android:trackTint="@drawable/newtrack"
        android:thumbTint="@drawable/newthumb"
         />
مهند عطية
la source
1
Cela marche. Cependant, il convient de noter qu'AndroidStudio ne pourra pas proposer de ressources @drawable pour trackTintou thumbTint. Il faut l'écrire manuellement et cela fonctionne.
Benjamin Basmaci
Pour une raison quelconque, c'est la seule réponse qui fonctionne de manière fiable sur mon Huawei. Merci!
einUsername
7

Dans Android Lollipop et supérieur, définissez-le dans votre style de thème:

<style name="BaseAppTheme" parent="Material.Theme">
    ...
    <item name="android:colorControlActivated">@color/color_switch</item>
</style>
emen
la source
Le problème avec cette solution est qu'elle change également les couleurs de mes textes sélectionnés, ce qui n'est pas ce que je veux.
codewing
@codewing Bien sûr que ce sera le cas. Parce que cela est défini dans la préférence de style globale. Afin d'atteindre votre objectif, c'est de trouver l'ID de vue de votre vue cible et de modifier ses attributs.
emen
OK, c'est pour la position "On". Qu'en est-il du changement de la couleur du pouce pour la position «Off»?
TavernSenses
7

Créez votre propre image à 9 patchs et définissez-la comme arrière-plan du bouton bascule.

http://radleymarx.com/2011/simple-guide-to-9-patch/

vous786
la source
2
Ouais, pourrait faire ça, mais il DOIT sûrement y avoir un moyen plus simple? Sélecteurs peut-être?
JamesSugrue
Non, il n'y a pas de moyen plus simple. Vous ne pouvez pas changer la couleur d'une image comme par magie :)
you786
Bon point. Je n'ai pas pleinement compris comment cela fonctionnait avant d'avoir un examen plus approfondi.
JamesSugrue
@Denizen, êtes-vous sûr? Si tel est le cas, postez une réponse et je voterai.
you786
@Denizen Veuillez supprimer votre commentaire. Android Switch renvoie toujours null pour getBackground (), j'ai perdu 30 minutes à essayer cela.
Shirish Herwade
5

La solution proposée par arlomedia a fonctionné pour moi. À propos de son problème d'extraspace, j'ai résolu la suppression de tous les rembourrages du commutateur.

ÉDITER

Comme demandé, voici ce que j'ai.

Dans le fichier de disposition, mon commutateur est à l'intérieur d'une disposition linéaire et après un TextView.

<LinearLayout
        android:id="@+id/myLinearLayout"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal|center"
        android:gravity="right"
        android:padding="10dp"
        android:layout_marginTop="0dp"
        android:background="@drawable/bkg_myLinearLayout"
        android:layout_marginBottom="0dp">
        <TextView
            android:id="@+id/myTextForTheSwitch"
            android:layout_height="wrap_content"
            android:text="@string/TextForTheSwitch"
            android:textSize="18sp"
            android:layout_centerHorizontal="true"
            android:layout_gravity="center_horizontal|center"
            android:gravity="right"
            android:layout_width="wrap_content"
            android:paddingRight="20dp"
            android:textColor="@color/text_white" />
        <Switch
            android:id="@+id/mySwitch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textOn="@string/On"
            android:textOff="@string/Off"
            android:layout_centerHorizontal="true"
            android:layout_gravity="center_horizontal"
            android:layout_toRightOf="@id/myTextForTheSwitch"
            android:layout_alignBaseline="@id/myTextForTheSwitch"
            android:gravity="right" />
    </LinearLayout>

Depuis que je travaille avec Xamarin / Monodroid (min. Android 4.1), mon code est:

Android.Graphics.Color colorOn = Android.Graphics.Color.Green;
Android.Graphics.Color colorOff = Android.Graphics.Color.Gray;
Android.Graphics.Color colorDisabled = Android.Graphics.Color.Green;

StateListDrawable drawable = new StateListDrawable();
drawable.AddState(new int[] { Android.Resource.Attribute.StateChecked }, new ColorDrawable(colorOn));
drawable.AddState(new int[] { -Android.Resource.Attribute.StateEnabled }, new ColorDrawable(colorDisabled));
drawable.AddState(new int[] { }, new ColorDrawable(colorOff));

swtch_EnableEdit.ThumbDrawable = drawable;

swtch_EnableEdit est précédemment défini comme ceci (Xamarin):

Switch swtch_EnableEdit = view.FindViewById<Switch>(Resource.Id.mySwitch);

Je ne règle pas du tout les paddings et je n'appelle pas .setPadding (0, 0, 0, 0).

Daniele D.
la source
Pouvez-vous fournir un code pour cela? J'ai essayé switchInput.setPadding (0, 0, 0, 0) mais rien n'a changé.
arlomedia
1
Testé dans Xamarin à l'aide de la bibliothèque AppCompat pour cibler 5.x et cela a fonctionné comme annoncé.
Alex.Ritna
4

vous pouvez créer un style personnalisé pour le widget de commutation qui utilise l'accent de couleur par défaut lorsque vous créez un style personnalisé

<style name="switchStyle" parent="Theme.AppCompat.Light">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorPrimary</item>    <!-- set your color -->
</style>    
yousef
la source
1

Essayez de trouver la bonne réponse ici: Sélecteur sur la couleur de fond de TextView . En deux mots, vous devez créer la forme en XML avec la couleur, puis l'affecter à l'état "coché" dans votre sélecteur.

Shamm
la source
Belle solution, mais savez-vous comment changer la couleur de manière dynamique?
inverted_index
Il vous suffit de définir le sélecteur comme ressource d'arrière-plan
Shamm
1

Je ne sais pas comment le faire à partir de java, mais si vous avez un style défini pour votre application, vous pouvez ajouter cette ligne dans votre style et vous aurez la couleur souhaitée pour moi, j'ai utilisé # 3F51B5

<color name="ascentColor">#3F51B5</color>
Erluxman
la source
1

Le moyen le plus simple consiste à définir la teinte de la piste et à définir le mode de teinte sur src_over pour supprimer 30% de transparence.

android:trackTint="@drawable/toggle_style"
android:trackTintMode="src_over"

toggle_style.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/informationDefault"
        android:state_checked="true"
        />
    <item android:color="@color/textDisabled" android:state_checked="false"/>
</selector>
Ege Kuzubasioglu
la source
0

En complément des réponses existantes: vous pouvez personnaliser le pouce et le suivi à l'aide des sélecteurs du res/colordossier, par exemple:

switch_track_selector

<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/lightBlue"
        android:state_checked="true" />
    <item android:color="@color/grey"/>
</selector>

switch_thumb_selector

<selector
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/darkBlue"
        android:state_checked="true" />
    <item android:color="@color/white"/>
</selector>

Utilisez ces sélecteurs pour personnaliser les teintes des pistes et des pouces:

<androidx.appcompat.widget.SwitchCompat
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:trackTint="@color/switch_track_selector"
    app:thumbTint="@color/switch_thumb_selector"/>

Gardez à l'esprit que si vous utilisez standart Switchet androidnamespace pour ces attributs, cela ne fonctionnera que pour l'API 23 et versions ultérieures, utilisez donc SwitchCompatavec appnamespacexmlns:app="http://schemas.android.com/apk/res-auto" comme solution universelle.

Résultat:

entrez la description de l'image ici

stay4life
la source
0

En xml, vous pouvez changer la couleur comme suit:

 <androidx.appcompat.widget.SwitchCompat
    android:id="@+id/notificationSwitch"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:checked="true"
    app:thumbTint="@color/darkBlue"
    app:trackTint="@color/colorGrey"/>

Dynamiquement, vous pouvez changer comme:

Switch.thumbDrawable.setColorFilter(ContextCompat.getColor(requireActivity(), R.color.darkBlue), PorterDuff.Mode.MULTIPLY)
ROHIT LIEN
la source
-1

Solution pour Android Studio 3.6:

yourSwitch.setTextColor(getResources().getColor(R.color.yourColor));

Modifie la couleur du texte de a dans la valeur définie dans le fichier XML de couleur (yourColor).

ChristianYami
la source