Cambiar el color “encendido” de un interruptor

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 encendido del Botón de Alternar desde el azul claro estándar al verde.

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

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

 values/themes.xml:  

ref: Android Developers Blog

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

Estilo

   

Colores

enter image description here

Diseño

  

Resultado

Ver cambio de colores para activar y desactivar el interruptor

enter image description here

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 “pista” del interruptor. Creo que es porque todavía estoy usando la imagen de la pista predeterminada, que tiene un espacio vacío a su alrededor. Sin embargo, cuando intenté personalizar la imagen de la pista con esta técnica, mi interruptor parecía tener una altura de 1 píxel con solo una pequeña porción del texto encendido / apagado que aparecía. Debe haber una solución para eso, pero aún no lo he encontrado …

Actualización para Android 5.1

En Android 5.1, el código anterior hace que el interruptor desaparezca por completo. Deberíamos poder usar el nuevo método setButtonTintList , pero esto no tuvo ningún efecto cuando lo probé. Ahora estoy usando este código:

 switchInput.getThumbDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY); switchInput.getTrackDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY); 

El único inconveniente es que no hay forma de establecer el color para el estado desactivado. La pista se vuelve más difuminada, pero el dedo pulgar permanece del mismo color, por lo que el cambio es más sutil de lo que me gustaría.

Actualización para Android 5.1.1

Aparentemente, el método setButtonTintList () tenía un error en 5.1 que se ha corregido en 5.1.1. Este código ahora funciona como se espera, sin inconvenientes que puedo ver:

 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.setButtonTintList(buttonStates); 

Actualización para Android 6-7

En Android 6-7, setButtonTintList se ignora en los switches. Como dijo Cheruby en los comentarios, podemos usar el nuevo setThumbTintList y eso funcionó como esperaba. También podemos usar setTrackTintList , pero aplica el color como una mezcla, con un resultado que es más oscuro de lo esperado en los temas de color oscuro y más claro de lo esperado en los temas de color claro, a veces hasta el punto de ser invisible. En Android 7, pude minimizar ese cambio anulando el modo de matiz de pista, pero no pude obtener resultados decentes en Android 6. Es posible que necesite definir colores adicionales que compensen la mezcla. (¿Alguna vez siente 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); } 

Crea un cambio personalizado y anula 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(); } } } } 

Para cambiar el estilo de cambio sin usar el código style.xml o Java, puede personalizar el cambio al formato XML:

  

Es un atributo de Android: thumbTint y android: trackTint que le permitió personalizar el color

Este es el resultado visual de este XML:

enter image description here

Si bien la respuesta de SubChord es correcta, realmente no responde la pregunta de cómo configurar el color “encendido” sin afectar también a otros widgets. Para hacer esto, use ThemeOverlay en styles.xml:

  

Y haz referencia en tu cambio:

  

Al hacerlo, SÓLO afectará el color de las vistas a las que desea aplicarlo.

Lo resolví actualizando el filtro de color cuando cambió el estado del conmutador …

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

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

  android:thumb="your drawable here" 

Crea tu propia imagen de 9 parches y configúrala como fondo del botón de alternar.

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

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

  

La solución sugerida por Arlomedia funcionó para mí. Sobre su problema de espacio extra, resolví quitar todos los rellenos al 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.

     

Como estoy trabajando con Xamarin / Monodroid (mínimo 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 define previamente así (Xamarin):

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

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

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í que he usado # 3F51B5

 #3F51B5 

Intente encontrar la respuesta correcta aquí: Selector en el color de fondo de TextView . En dos palabras, debe crear Shape en XML con color y luego asignarlo para indicar “marcado” en su selector.

puede hacer un estilo personalizado para el widget de cambio que use acento de color como predeterminado cuando haga un estilo personalizado para él

  

Puede probar esta lib, fácil de cambiar de color para el botón de cambio.
https://github.com/kyleduo/SwitchButton enter image description here