Cambiar el color "encendido" de un interruptor


156

Estoy usando un control Switch estándar con el tema holo.light en una aplicación ICS.

Quiero cambiar el color de estado resaltado o activado del botón de alternar del azul claro estándar al verde.

Esto debería ser fácil, pero parece que no puedo entender cómo hacerlo.


Realmente no veo otra manera que copiar los recursos de plataforma relevantes (selector y archivos * .png) y modificar el estado 'on' dibujable. No olvide señalar el Switchselector personalizado después.
MH.

Respuestas:


100

A partir de ahora, es mejor usar SwitchCompat de la biblioteca AppCompat.v7. Luego puede usar un estilo simple para cambiar el color de sus componentes.

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 de desarrolladores de Android

EDITAR :

La forma en que se debe aplicar correctamente es a través android:theme="@style/Theme.MyTheme" y también se puede aplicar a estilos primarios como EditTexts, RadioButtons, Switches, CheckBoxes y ProgressBars:

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

<style name="My.Widget.Checkbox" parent="Widget.AppCompat.CompoundButton.CheckBox">

1
Aunque no es aplicable en el momento, ¡esta debería ser la respuesta aceptada!
Andrew Gallasch

He cambiado esto a la respuesta aceptada, ya que parece el enfoque más "moderno" a esta pregunta.
JamesSugrue

1
Intenté todo esto y ninguno de ellos cambió el color del estado "encendido" para mi interruptor.
Adam Johns

31
'on' es colorAccent, 'off' es colorSwitchThumbNormal. Si usa el AppCompattema, debe usarlo en SwitchCompatlugar de hacerlo Switch. Si usa SDK 23+, puede usar android:thumbTinty android:thumbTintModecon a ColorStateList.
Tom

1
@ Tom PLZ respuesta será esos 'android: thumbTint' cosas van a funcionar en dispositivos <23
Shirish Herwade

269

Tarde para la fiesta, pero así es como lo hice

Estilo

 <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>

Colores

ingrese la descripción de la imagen aquí

Diseño

<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" />

Resultado

Ver cambio de colores para activar y desactivar interruptor

ingrese la descripción de la imagen aquí


14
@MaksimKniazev Tienes que usar SwitchCompat;)
Ovi Trif

1
Bien, excepto por colorControlActivated: no establece el color de la pista, solo el color del pulgar.
Puntero nulo el

1
Aquí hay una solución para Switch y SwitchCompat: stackoverflow.com/a/47036089/5869630
roghayeh hosseini

Las etiquetas <style> debían escribirse bajo res >> values ​​>> styles.xml y en la página XML para <Switch ...> solo debe agregar la línea llamada: android: theme = "@ style / SCBSwitch y mis colores son : colorControlActivated "> # ff0000 y colorSwitchThumbNormal"> # 00ff00 y android: colorForeground "> # 00ff00
Bay

@OviTrif ¡Impresionante! Es impresionante lo difícil que es encontrar una información simple como esa. Muchas y muchas respuestas que he estado leyendo, y nadie, dio una respuesta funcional hasta ahora. ¡Finalmente!
jairhumberto

49

Esto funciona para mí (requiere 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);

Tenga en cuenta que el estado "predeterminado" debe agregarse al final como se muestra aquí.

El único problema que veo es que el "pulgar" del interruptor ahora parece más grande que el fondo o la "pista" del interruptor. Creo que es porque todavía estoy usando la imagen de pista predeterminada, que tiene un espacio vacío a su alrededor. Sin embargo, cuando intenté personalizar la imagen de la pista usando esta técnica, mi interruptor parecía tener una altura de 1 píxel con solo un fragmento del texto de encendido / apagado que aparecía. Debe haber una solución para eso, pero aún no la he encontrado ...

Actualización para Android 5

En Android 5, el código anterior hace que el interruptor desaparezca por completo. Deberíamos poder usar el nuevo setButtonTintList método , pero esto parece ignorarse para los modificadores. Pero esto funciona:

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

Actualización para Android 6-7

Como Cheruby dijo en los comentarios, podemos usar lo nuevo setThumbTintListy funcionó como se esperaba para mí. También podemos usar setTrackTintList, pero eso aplica el color como una mezcla, con un resultado que es más oscuro de lo esperado en temas de color oscuro y más claro de lo esperado en temas de color claro, a veces hasta el punto de ser invisible. En Android 7, pude minimizar ese cambio anulando el modo de tinte de pista , pero no pude obtener resultados decentes en Android 6. Es posible que deba definir colores adicionales que compensen la fusión. (¿Alguna vez tiene la sensación de que Google no quiere que personalicemos la apariencia de nuestras aplicaciones?)

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

Estoy usando el enfoque getThumbDrawable / getTrackDrawable para crear un interruptor donde ambos estados tienen el mismo color; en otras palabras, el interruptor no habilita / deshabilita algo, pero se usa para elegir entre dos alternativas.
Natix

44
Obtuve que DrawableCompat.setTintList le permitirá trabajar en dispositivos anteriores. Llamo a: DrawableCompat.setTintList (switchCompat.getThumbDrawable (), foregroundState);
Alexey

Edite la respuesta para incluir la solución DrawableCompat. Funciona perfectamente!
Dmytro Karataiev el

API 23+: también switchInput.setThumbTintList(buttonStates); funciona para Nougat. API 21-22: Use DrawableCompat como lo sugiere @Alexey. El switchInput.setButtonTintList(buttonStates);no funcionó para mí, que no colorear los estados para mi interruptor. API por debajo de 21: switchInput.getThumbDrawable().setColorFilter(someColor, PorterDuff.Mode.SrcIn); Esto funcionó para mí. También trabajé con Xamarin, así que traduzca esos a C # en los renderizadores de Android si usa Xamarin.Forms.
Cheruby

37

Para cambiar el estilo de Switch sin usar style.xml o código Java, puede personalizar el switch en XML de diseño:

<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" />

Su atributo android: thumbTint y android: trackTint le permitieron personalizar el color.

Este es el resultado visual para este XML:

ingrese la descripción de la imagen aquí


17
Esto cambia el color del pulgar, sin importar si está activado o desactivado.
Desarrollador de Android

1
"El atributo thumbTint solo se usa en API nivel 21 y superior"
norbDEV

66
@norbDEV usa la aplicación: thumbTint y app: trackTint con SwitchCompat de la biblioteca AppCompat.v7 para un nivel API más bajo.
David Darias

Eso funciona, pero ¿qué pasa si desea cambiar el color del pulgar, dependiendo de si está activado o no?
TavernSenses

2
Si desea usar thumbTint debajo de 21, use en app:thumbTintlugar de android:thumbTinty cambie switchconSwitchCompat
Kavita_p

33

Cree un conmutador personalizado y anule setChecked para cambiar el color:

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

2
La primera publicación que realmente me ayudó a lograr un color personalizado para el cambio de material sin usar estilo o temas. Gracias !
Mackovich el

1
Agradable. Ya tenía mi propio Switch personalizado, así que solo tuve que anular el método setChecked y todos cambiaron automáticamente sus colores. Gracias desde españa.
Julio

22

Si bien la respuesta de SubChord es correcta, en realidad no responde a la pregunta de cómo configurar el color "activado" sin afectar también a otros widgets. Para hacer esto, use a ThemeOverlayen styles.xml:

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

Y consúltalo en tu interruptor:

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

Al hacerlo, SOLO afectará el color de las vistas a las que desea aplicarlo.


Por alguna razón, también tuve que establecer "colorControlActivated" en el mismo valor, pero en POC, fue suficiente para usar "colorAccent". ¿Cómo?
Desarrollador de 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"/>

Y dentro 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>

thumbTintsolo se aplica en Android API 21 y superior. ¿Cómo si quiero cambiar el color debajo de Android 21?
Giovanka Bisano

developer.android.com/reference/android/support/v7/widget/… SwitchCompat es compatible con versiones anteriores de API 7 y superior
equipo de equipo

1
Es 2020. Realmente me pregunto en qué parte del mundo la gente sigue usando Android 21 y versiones anteriores.
zeeshan

18

Lo resolví actualizando el filtro de color cuando se cambió el estado del interruptor ...

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

13

Puede ser un poco tarde, pero para los botones de cambio, el botón toogle no es la respuesta, debe cambiar el dibujo en el parámetro xml del cambio:

 android:thumb="your drawable here"

9

hacer dibujable "newthumb.xml"

<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>

y hacer dibujable "newtrack.xml"

<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>

y agregarlo en Switch:

<Switch
        android:trackTint="@drawable/newtrack"
        android:thumbTint="@drawable/newthumb"
         />

1
Esto funciona. Sin embargo, debe tenerse en cuenta que AndroidStudio no podrá sugerir recursos @drawable para trackTinto thumbTint. Uno necesita escribirlo manualmente y funciona.
Benjamin Basmaci

Por alguna razón, esta es la única respuesta que funciona de manera confiable en mi Huawei. ¡Gracias!
einUsername

7

En Android Lollipop y superior, defínalo en el estilo de tu tema:

<style name="BaseAppTheme" parent="Material.Theme">
    ...
    <item name="android:colorControlActivated">@color/color_switch</item>
</style>

El problema con esta solución es que también cambia los colores de mis mensajes de texto seleccionados, que no es lo que quiero.
codewing

@codewing Por supuesto que lo hará. Porque esto se establece en la preferencia de estilo global. Para lograr su objetivo, es encontrar el id de vista de su vista de destino y modificar sus atributos.
emen

OK, eso es para la posición "On". ¿Qué pasa con el cambio del color del pulgar para la posición "Off"?
TavernSenses

7

Cree su propia imagen de 9 parches y configúrela como fondo del botón de alternar.

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


2
Sí, podría hacer eso, pero seguramente DEBE haber una manera más fácil. ¿Selectores tal vez?
JamesSugrue

No, no hay forma más fácil. No puedes cambiar mágicamente el color de una imagen :)
you786

Buen punto. No entendí completamente cómo funcionaba hasta que tuve una mirada más profunda.
JamesSugrue

@Denizen, ¿estás seguro? Si es así, publique una respuesta y la votaré.
you786

@Denizen Por favor, elimine su comentario. Android Switch siempre devuelve nulo para getBackground (), perdí 30 minutos intentando esto.
Shirish Herwade

5

La solución sugerida de arlomedia funcionó para mí. Sobre su problema de espacio extra resolví quitar todos los rellenos del interruptor.

EDITAR

Según lo solicitado, aquí lo que tengo.

En el archivo de diseño, mi interruptor está dentro de un diseño lineal y después de 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>

Como estoy trabajando con Xamarin / Monodroid (min. Android 4.1) mi código es:

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 se definió anteriormente de esta manera (Xamarin):

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

No configuro en todos los rellenos y no llamo .setPadding (0, 0, 0, 0).


¿Puedes proporcionar un código para eso? Intenté switchInput.setPadding (0, 0, 0, 0) pero nada cambió.
arlomedia

1
Probado en Xamarin usando la biblioteca AppCompat para apuntar a 5.xy esto funcionó como se anuncia.
Alex.Ritna

4

puede hacer un estilo personalizado para el widget de cambio que usa el acento de color como predeterminado cuando lo hace con un estilo personalizado

<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>    



1

No sé cómo hacerlo desde Java, pero si tiene un estilo definido para su aplicación, puede agregar esta línea en su estilo y tendrá el color deseado para mí, he usado # 3F51B5

<color name="ascentColor">#3F51B5</color>

1

La forma más fácil es definir el tinte de la pista y establecer el modo de tinte en src_over para eliminar el 30% de transparencia.

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>

0

Como una adición a las respuestas existentes: puede personalizar el pulgar y la pista usando selectores en la res/colorcarpeta, por ejemplo:

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>

Use estos selectores para personalizar pistas y tintes de pulgar:

<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"/>

Tenga en cuenta que si usa standart Switchy androidespacio de nombres para estos atributos, solo funcionará para API 23 y posterior, así que use SwitchCompatcon appespacio de nombresxmlns:app="http://schemas.android.com/apk/res-auto" como solución universal.

Resultado:

ingrese la descripción de la imagen aquí


0

En xml, puede cambiar el color como:

 <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"/>

Dinámicamente puedes cambiar como:

Switch.thumbDrawable.setColorFilter(ContextCompat.getColor(requireActivity(), R.color.darkBlue), PorterDuff.Mode.MULTIPLY)

-1

Solución para Android Studio 3.6:

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

Cambia el color del texto de un valor definido en el archivo XML de color (yourColor).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.