Este tutorial te enseña sobre el uso del componente Switch en Compose en Android a través de varios ejemplos fáciles de comprender.
El Switch es un control de selección que te permite elegir entre dos posibles estados. Cambia entre sus valores arrastrando la palanca redondeada (thumb), sobre el carril (track) en el que se encuentra. O simplemente haz click en el componente para alternar entre estados.
Ejemplos De Switch En Compose
El código de los ejemplos de este tutorial los encontrarás en el paquete examples/Switch
del paquete p7_componentes
.
Los ejemplos son desplegados (como se muestra en la siguiente imagen) desde la función SwitchScreen()
en SwitchScreen.kt
:
1. Crear Un Switch
Invoca la función Switch()
para construir y mostrar en pantalla un Switch. La cual está definida con la siguiente firma en la documentación oficial:
@Composable
fun Switch(
checked: Boolean?,
onCheckedChange: ((Boolean) -> Unit)?,
modifier: Modifier? = Modifier,
enabled: Boolean? = true,
interactionSource: MutableInteractionSource? = remember { MutableInteractionSource() },
colors: SwitchColors? = SwitchDefaults.colors()
): Unit
Sus parámetros cumplen con:
checked
: Determina si el switch se encuentra en estado On u OffonCheckedChange
: Función invocada cuando el switch ha sido clickeadoenabled
: Determina si el switch está habilitado o deshabilitadocolors
: Instancia deSwitchColors
para representar los colores del thumb y el track en diferentes estados
Ejemplo: Un Switch Simple
Para crear un Switch en su forma básica, como ves en la figura 1, implementa el siguiente código Kotlin:
@Composable
fun SimpleSwitch() {
val isOn = remember { mutableStateOf(true) }
Switch(
checked = isOn.value,
onCheckedChange = { newState -> isOn.value = newState }
)
}
Su estado inicial es On, ya que la variable de estado isOn
es inicializada con true
. Adicionalmente, alternamos entre estados, al modificar el valor de isOn
desde una lambda asignada a onCheckedChange
.
Si ejecutas la App de ejemplo o previsualizas la función Example1()
en modo de interacción, experimentarás la secuencia de Resultado 1.
@Composable
fun Example1() {
SimpleSwitch()
}
Nota: Esta implementación es sumamente similar a la del control RadioButton
.
2. Añadir Etiqueta A Un Switch
Para aclarar la opción que el switch controla y el estado actual de la misma, es necesario incorporar una etiqueta de texto como se ve en la Figura 2.
A diferencia del SwitchView
en el sistema de views, cuyo atributo android:text
permite definir la etiqueta, la función Switch()
en Compose no la trae como parámetro.
Ejemplo: Switch Con Etiqueta
Tomemos como ejemplo el registro de un usuario en un servicio, donde se le desea ofrecer el envío de ofertas especiales a su correo electrónico.
Con el fin de llegar a la solución, (similar al CheckBox y el RadioButton) es necesario crear un layout que envuelva tanto la etiqueta, como el control Switch.
Las siguientes son las tareas para llevarlo a cabo:
- Crear una función componible que eleve el estado del switch y reciba la etiqueta como parámetro
- Invocar a la función
Box()
- Incluir un elemento
Text()
alineado al centro|inicio y luego unoSwitch()
alineado al centro|final - Trasladar el cambio de estado desde el Switch hacia la fila con el modificador
toggeable()
Atendiendo los lineamientos anteriores, la nueva función componible para representar un switch con etiqueta será:
@Composable
fun LabelledSwitch( // (1)
modifier: Modifier = Modifier,
checked: Boolean,
label: String,
onCheckedChange: ((Boolean) -> Unit),
enabled: Boolean = true,
colors: SwitchColors = SwitchDefaults.colors()
) {
Box( // (2)
modifier = modifier
.fillMaxWidth()
.height(56.dp)
.toggleable( // (4)
value = checked,
onValueChange = onCheckedChange,
role = Role.Switch,
enabled = enabled
)
.padding(horizontal = 16.dp)
) {
CompositionLocalProvider(
LocalContentAlpha provides
if (enabled) ContentAlpha.high else ContentAlpha.disabled
) {
Text( // (3)
text = label,
style = MaterialTheme.typography.body1,
modifier = Modifier
.align(Alignment.CenterStart)
.padding(end = 16.dp)
)
}
Switch( // (3)
checked = checked,
onCheckedChange = null, // (4)
enabled = enabled,
colors = colors,
modifier = Modifier.align(Alignment.CenterEnd)
)
}
}
Cabe aclarar que cuando se procesa el estado deshabilitado, el texto debe cambiar su énfasis a ContentAlpha.disabled
. Esto mejora la expresividad del conjunto.
Al final, invoca la anterior función de la siguiente manera:
@Composable
fun Example2() {
val offersReceiving = "Recibir ofertas especiales"
val offersReceivingState = remember { mutableStateOf(true) }
LabelledSwitch(
checked = offersReceivingState.value,
label = offersReceiving,
onCheckedChange = { offersReceivingState.value = it }
)
}
Al ejecutar o entrar a modo interactivo podrás ver el siguiente resultado:
3. Deshabilitar Un Switch
Deshabilitar un switch es intuitivo, basta con pasar false
como argumento al parámetro enabled
de Switch()
. Esto provocará que el control se torne de un tono grisáceo y no reciba eventos de entrada del usuario como se ven en la figura 3.
Ejemplo: Switch Deshabilitado
Supongamos que los usuarios de una App pueden activar la notificación de reportes semanales. No obstante, esta característica es solo para usuarios premium, por lo que debe deshabilitarse en caso contrario.
La solución consiste en:
- Recibir los ajustes del usuario que la App almacena
- Verificar que la propiedad de su tipo de plan sea correcto
- Crear un switch con etiqueta y pasar la evaluación anterior a
enabled
En código Kotlin esto significa:
@Composable
fun Example3() {
val (isPremium, setIsPremium) = remember { mutableStateOf(false) }
val (notifyWeekly, setNotifyWeekly) = remember { mutableStateOf(false) }
Column(Modifier.padding(vertical = 16.dp)) {
LabelledCheckbox(
checked = isPremium,
onCheckedChange = setIsPremium,
label = "¿Usuario premium?"
)
Spacer(modifier = Modifier.height(56.dp))
LabelledSwitch(
checked = notifyWeekly,
label = "Habilitar informes semanales",
onCheckedChange = setNotifyWeekly,
enabled = isPremium
)
}
}
La utilidad del CheckBox
agregado es simular los dos escenarios posibles para el plan del usuario, de esta forma veremos la desactivación del Switch.
Por supuesto, el valor de isPremium
debería ser obtenido desde una clase relacionada a la obtención de datos en nuestra App (comúnmente un ViewModel comunicado a un repositorio, servicio, dao, etc.).
4. Cambiar Color De Un Switch
Por último, veamos el caso en que requieras modificar el color de un Switch en sus diferentes estados. Con esto me refiero a cambiar el color de los elementos thumb y track.
Cómo viste al inicio, el atributo colors
recibe una instancia de SwitchColors
para este cometido. La forma de fabricarla es con la función SwitchDefaults.colors()
:
@Composable
fun colors(
checkedThumbColor: Color? = MaterialTheme.colors.secondaryVariant,
checkedTrackColor: Color? = checkedThumbColor,
checkedTrackAlpha: Float? = 0.54f,
uncheckedThumbColor: Color? = MaterialTheme.colors.surface,
uncheckedTrackColor: Color? = MaterialTheme.colors.onSurface,
uncheckedTrackAlpha: Float? = 0.38f,
disabledCheckedThumbColor: Color? = checkedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colors.surface),
disabledCheckedTrackColor: Color? = checkedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colors.surface),
disabledUncheckedThumbColor: Color? = uncheckedThumbColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colors.surface),
disabledUncheckedTrackColor: Color? = uncheckedTrackColor
.copy(alpha = ContentAlpha.disabled)
.compositeOver(MaterialTheme.colors.surface)
): SwitchColors
La configuración de parámetros nombrados obedece a los valores checked (On) y unchecked (Off) y al estado disabled (deshabilitado). Sumado al componente que se modifica: thumb o track.
Ejemplo: Switch Con Color Modificado
Basemonos en el ejemplo 3 para modificar el color de la pista y la palanca por los siguientes:
- Palanca -> On + Habilitado = Azul 500
- Pista -> On + Habilitado = Azul Claro 500
- Pista -> Off + Habilitado = Azul Claro 300
Con lo anterior en mente, solo resta definir los colores y aplicarlos con la función SwitchDefaults.colors()
:
val Blue500 = Color(0xFF2196F3)
val LightBlue500 = Color(0xFF00BCD4)
val LightBlue300 = Color(0xFF4DD0E1)
@Composable
fun Example4() {
val (isPremium, setIsPremium) = remember { mutableStateOf(false) }
val (notifyWeekly, setNotifyWeekly) = remember { mutableStateOf(false) }
Column(Modifier.padding(vertical = 16.dp)) {
LabelledCheckbox(
checked = isPremium,
onCheckedChange = setIsPremium,
label = "¿Usuario premium?"
)
Spacer(modifier = Modifier.height(56.dp))
LabelledSwitch(
checked = notifyWeekly,
label = "Habilitar informes semanales",
onCheckedChange = setNotifyWeekly,
enabled = isPremium,
colors = SwitchDefaults.colors(
checkedThumbColor = Blue500,
uncheckedThumbColor = LightBlue500,
uncheckedTrackColor = LightBlue300
)
)
}
}
El resultado final luciría así:
Únete Al Discord De Develou
Si tienes problemas con el código de este tutorial, preguntas, recomendaciones o solo deseas discutir sobre desarrollo Android conmigo y otros desarrolladores, únete a la comunidad de Discord de Develou y siéntete libre de participar como gustes. ¡Te espero!