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 setThumbTintList
y 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);
}
Switch
selector personalizado después.