web-dev-qa-db-fra.com

Comment changer la couleur d'un SwitchCompat

J'ai quelques commutateurs avec des couleurs différentes dans mon application et pour changer leurs couleurs, j'ai utilisé un sélecteur personnalisable pour chaque commutateur.

Lorsque la nouvelle bibliothèque AppCompat v21 a été publiée, un nouveau contrôle Android.support.v7.widget.SwitchCompat existait.

Est-il possible de changer la couleur d'un SwitchCompat sans utiliser de dessin, par exemple en utilisant XML ou du code?

115
Orest

Ok, alors je suis désolé mais la plupart de ces réponses sont incomplètes ou ont un bug mineur. La réponse très complète de @ austyn-mahoney est correcte et constitue la source de cette réponse, mais elle est compliquée et vous souhaitez probablement simplement styler un commutateur. Le «style» des commandes à travers différentes versions d’Android est une épopée douleur dans le cul. Après avoir tiré mes cheveux pendant des jours sur un projet avec des contraintes de conception très strictes, je suis finalement tombé en panne et j'ai écrit une application de test. il a souvent l'autre. Voici ce que j'ai trouvé ...

_ {First: Vous ne pouvez en réalité styliser aucun d'entre eux, mais vous pouvez appliquer un thème à chacun d'entre eux, ou à un seul d'entre eux.

Second: Vous pouvez tout faire à partir de XML et vous n'avez pas besoin d'un second value-v21/styles.xml.

Third: en ce qui concerne les commutateurs, vous avez le choix entre deux options de base si vous souhaitez prendre en charge les anciennes versions d'Android (comme vous le savez sûrement) ...

  1. Vous pouvez utiliser une SwitchCompat et vous pourrez lui donner la même apparence sur toutes les plateformes.
  2. Vous pouvez utiliser une variable Switch et vous pourrez la thématiser avec le reste de votre thème ou simplement avec ce commutateur particulier. Sur les anciennes versions d'Android, vous verrez simplement un commutateur carré plus ancien et sans style.

Ok maintenant pour le code de référence simple. Encore une fois si vous créez un simple Hello World! et déposez ce code dans vous pouvez jouer au contenu de votre coeur. Tout cela est une plaque chauffante ici, donc je vais simplement inclure le code XML pour l'activité et le style ...

activity_main.xml ...

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.kunai.switchtest.MainActivity">

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="'Styled' SwitchCompat" />

    <Android.support.v7.widget.SwitchCompat
        Android:id="@+id/switch_item"
        Android:layout_width="wrap_content"
        Android:layout_height="46dp"
        Android:layout_alignParentEnd="true"
        Android:layout_marginEnd="16dp"
        Android:checked="true"
        Android:longClickable="false"
        Android:textOff="OFF"
        Android:textOn="ON"
        app:switchTextAppearance="@style/BrandedSwitch.text"
        app:theme="@style/BrandedSwitch.control"
        app:showText="true" />

</RelativeLayout>

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.kunai.switchtest.MainActivity">

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Themed SwitchCompat" />

    <Android.support.v7.widget.SwitchCompat
        Android:id="@+id/switch_item2"
        Android:layout_width="wrap_content"
        Android:layout_height="46dp"
        Android:layout_alignParentEnd="true"
        Android:layout_marginEnd="16dp"
        Android:checked="true"
        Android:longClickable="false" />

</RelativeLayout>

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.kunai.switchtest.MainActivity">

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Themed Switch" />

    <Switch
        Android:id="@+id/switch_item3"
        Android:layout_width="wrap_content"
        Android:layout_height="46dp"
        Android:layout_alignParentEnd="true"
        Android:layout_marginEnd="16dp"
        Android:checked="true"
        Android:longClickable="false"
        Android:textOff="OFF"
        Android:textOn="ON"/>

</RelativeLayout>

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.kunai.switchtest.MainActivity">

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="'Styled' Switch" />

    <Switch
        Android:id="@+id/switch_item4"
        Android:layout_width="wrap_content"
        Android:layout_height="46dp"
        Android:layout_alignParentEnd="true"
        Android:layout_marginEnd="16dp"
        Android:checked="true"
        Android:longClickable="false"
        Android:textOff="OFF"
        Android:textOn="ON"
        Android:theme="@style/BrandedSwitch"/>

</RelativeLayout>

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.kunai.switchtest.MainActivity">

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="'Styled' CheckBox" />

    <CheckBox
        Android:id="@+id/checkbox"
        Android:layout_width="wrap_content"
        Android:layout_height="46dp"
        Android:layout_alignParentEnd="true"
        Android:layout_marginEnd="16dp"
        Android:checked="true"
        Android:longClickable="false"
        Android:theme="@style/BrandedCheckBox"/>

</RelativeLayout>

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.kunai.switchtest.MainActivity">

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Themed CheckBox" />

    <CheckBox
        Android:id="@+id/checkbox2"
        Android:layout_width="wrap_content"
        Android:layout_height="46dp"
        Android:layout_alignParentEnd="true"
        Android:layout_marginEnd="16dp"
        Android:checked="true"
        Android:longClickable="false"/>

</RelativeLayout>

styles.xml ...

<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">#3F51B5</item>
    <item name="colorPrimaryDark">#303F9F</item>
    <item name="colorAccent">#FF4081</item>
</style>

<style name="BrandedSwitch.control" parent="Theme.AppCompat.Light">
    <!-- active thumb & track color (30% transparency) -->
    <item name="colorControlActivated">#e6e600</item>
    <item name="colorSwitchThumbNormal">#cc0000</item>
</style>

<style name="BrandedSwitch.text" parent="Theme.AppCompat.Light">
    <item name="Android:textColor">#ffa000</item>
    <item name="Android:textSize">9dp</item>
</style>

<style name="BrandedCheckBox" parent="AppTheme">
    <item name="colorAccent">#aaf000</item>
    <item name="colorControlNormal">#ff0000</item>
</style>

<style name="BrandedSwitch" parent="AppTheme">
    <item name="colorAccent">#39ac39</item>
</style>

Je sais, je sais, vous êtes trop paresseux pour construire cela, vous voulez juste obtenir votre code écrit et l'enregistrer afin que vous puissiez fermer cette douleur dans le cul bug de cauchemar de compatibilité Android afin que le concepteur de votre équipe soit enfin heureux . J'ai compris. Voici à quoi ça ressemble quand vous le lancez ...

API_21:

 API 21

API_18:

 API18

52
Aaron Cooley

Je pense que la réponse dans le lien ci-dessous est meilleure

Comment changer la couleur de la piste d'un SwitchCompat

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
   ...
   <!-- Active thumb color & Active track color(30% transparency) -->
   <item name="colorControlActivated">@color/theme</item>
   <!-- Inactive thumb color -->
   <item name="colorSwitchThumbNormal">@color/grey300</item>
   <!-- Inactive track color(30% transparency) -->
   <item name="Android:colorForeground">@color/grey600</item>
   ...
</style>
12
megaKertz

Ainsi, certains jours, je manque de cellules cérébrales et: 

<Android.support.v7.widget.SwitchCompat
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        style="@style/CustomSwitchStyle"/>

n'applique pas le thème car le style est incorrect. Je devais utiliser app: theme: P 

<Android.support.v7.widget.SwitchCompat
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:theme="@style/CustomSwitchStyle"/>

Whoopsies. C'est ce message qui m'a permis de comprendre mon erreur. Espérons que si quelqu'un tombe par hasard dessus, cela l'aidera comme il l'a fait pour moi. Merci Gaëtan Maisse pour ta réponse

5
isuPatches

Soyez attentif au bogue connu avec SwitchCompat

C'est un bug avec un fichier corrompu dans drawable-hdpi sur AppCompat https://code.google.com/p/Android/issues/detail?id=78262

Pour le résoudre, remplacez-le simplement avec ces 2 fichiers https://github.com/lopespm/quick-fix-switchcompat-resources .__ Ajoutez-le dans votre répertoire drawable-hdpi

XML

<Android.support.v7.widget.SwitchCompat
Android:id="@+id/dev_switch_show_dev_only"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
/>

Et rien n'était nécessaire sur Java

2
Anthone
<Android.support.v7.widget.SwitchCompat
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:id="@+id/adamSwitch"
    Android:textColor="@color/top_color"
    Android:textAppearance="@color/top_color"
    Android:gravity="center"
    app:showText="true"
    app:theme="@style/Custom.Widget.SwitchCompat"
    app:switchPadding="5dp"
    />

dans style.xml

<style name="Custom.Widget.SwitchCompat" parent="Widget.AppCompat.CompoundButton.Switch" >
            <item name="Android:textColorPrimary">@color/blue</item>  <!--textColor on activated state -->
      </style>
1
NickUnuchek

Pour avoir un meilleur contrôle de la couleur de la piste (aucun changement d'alpha API contrôlé), j'ai étendu SwitchCompat et style les éléments par programme:

    public class CustomizedSwitch extends SwitchCompat {

    public CustomizedSwitch(Context context) {
        super(context);
        initialize(context);
    }

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

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

    public void initialize(Context context) {
        // DisplayMeasurementConverter is just a utility to convert from dp to px and vice versa
        DisplayMeasurementConverter displayMeasurementConverter = new DisplayMeasurementConverter(context);
        // Sets the width of the switch
        this.setSwitchMinWidth(displayMeasurementConverter.dpToPx((int) getResources().getDimension(R.dimen.tp_toggle_width)));
        // Setting up my colors
        int mediumGreen = ContextCompat.getColor(context, R.color.medium_green);
        int mediumGrey = ContextCompat.getColor(context, R.color.medium_grey);
        int alphaMediumGreen = Color.argb(127, Color.red(mediumGreen), Color.green(mediumGreen), Color.blue(mediumGreen));
        int alphaMediumGrey = Color.argb(127, Color.red(mediumGrey), Color.green(mediumGrey), Color.blue(mediumGrey));
        // Sets the tints for the thumb in different states
        DrawableCompat.setTintList(this.getThumbDrawable(), new ColorStateList(
                new int[][]{
                        new int[]{Android.R.attr.state_checked},
                        new int[]{}
                },
                new int[]{
                        mediumGreen,
                        ContextCompat.getColor(getContext(), R.color.light_grey)
                }));
        // Sets the tints for the track in different states
        DrawableCompat.setTintList(this.getTrackDrawable(), new ColorStateList(
                new int[][]{
                        new int[]{Android.R.attr.state_checked},
                        new int[]{}
                },
                new int[]{
                        alphaMediumGreen,
                        alphaMediumGrey
                }));
    }
}

Chaque fois que je veux utiliser la variable CustomizedSwitch, j'en ajoute simplement une à mon fichier xml.

1
Tom Howard

Juste

 Android:buttonTint="@color/primary"
0
Pablo Cegarra

Mon exemple de travail d'utilisation simultanée de style et d'Android: thème (API> = 21)

<Android.support.v7.widget.SwitchCompat
    Android:id="@+id/wan_enable_nat_switch"
    style="@style/Switch"
    app:layout_constraintBaseline_toBaselineOf="@id/wan_enable_nat_label"
    app:layout_constraintEnd_toEndOf="parent" />

<style name="Switch">
    <item name="Android:layout_width">wrap_content</item>
    <item name="Android:layout_height">wrap_content</item>
    <item name="Android:paddingEnd">16dp</item>
    <item name="Android:focusableInTouchMode">true</item>
    <item name="Android:theme">@style/ThemeOverlay.MySwitchCompat</item>
</style>

<style name="ThemeOverlay.MySwitchCompat" parent="">
    <item name="colorControlActivated">@color/colorPrimaryDark</item>
    <item name="colorSwitchThumbNormal">@color/text_outline_not_active</item>
    <item name="Android:colorForeground">#42221f1f</item>
</style>
0
Andrew Glukhoff