El Switch en Android es un widget con un control deslizante que te permite elegir entre dos posibles estados. Cambia entre sus valores arrastrando la palanca redondeada sobre el carril en el que se encuentra o simplemente haz click en el botón.
Su objetivo es informarle al usuario sobre la persistencia de un estado de activación/desactivación en un contexto dado. Algunos ejemplos de sus usos lo vemos en las preferencias de usuario de las apps, la persistencia de la activación de una alarma, habilitación de campos adicionales en un formulario y muchos otros.
La Clase Switch
En el SDK este widget está representado por la clase Switch
, la cual funciona desde la API 14 hacia arriba. También existe la clase SwitchCompat
para compatibilidades hasta la API 7 y SwitchMaterial
para crear switches con el tema de material design.
Claro está, que al ser hijas de CompoundButton
, tendrán acceso a los tres métodos de la interfaz Checkable
: isChecked()
para determinar si está activo, setChecked()
para cambiar el estado y toggle()
para invertir el valor del estado actual.
Agregar Switch En Android Studio
Para añadir elementos de la clase Switch
en el editor de layouts, dirígete a la paleta y haz click en la sección de Buttons. Luego arrastra la opción Switch a tu layout.
Recuerda que una forma más fácil de encontrarlo es usar la lupa para buscar al tipear el nombre del view.
Al agregarlo a un layout podrás ver una etiqueta <Switch>
similar a la siguiente:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Switch
android:id="@+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Switch"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Sin embargo, Android Studio te aconsejará que es mejor usar SwitchCompat
o SwitchMaterial
.
Por lo que usamos cualquiera de esos dos elementos en nuestra etiqueta. Por ejemplo:
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Switch"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Crear Switch Programaticamente
Cuando desees crear una instancia de la clase Switch
usa cualquier de sus constructores públicos disponibles.
Switch(Context context)
Switch(Context context, AttributeSet attrs)
Switch(Context context, AttributeSet attrs, int defStyleAttr)
Switch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
Por ejemplo, supongamos que nos encontramos en una actividad y deseamos crear un SwitchMaterial
dinámicamente. Si su padre fuera un ConstraintLayout
, entonces el código se vería así:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val root = findViewById<View>(R.id.layout) as ConstraintLayout
val switch = SwitchMaterial(this).apply {
text = "Switch agregado en tiempo de ejecución"
isChecked = true
}
root.addView(switch)
}
}
Escuchar Cambios De Estado
Usa el método setOnCheckedChangeListener()
para suscribir instancias del tipo OnCheckedChangedListener
con el fin de procesar los eventos de cambio de estado en el Switch
.
val switch = findViewById<SwitchMaterial>(R.id.switch1)
switch.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
// Acciones al estar activo
} else {
// Acciones al estar inactivo
}
}
Como ves, la expresión de objeto puede convertirse en una función lambda, cuyos parámetros son el CompoundButton
alterado (buttonView
) y su estado de activación (isChecked
).
Cambiar Tema De Un Switch
A la hora de realizar modificaciones a las propiedades visuales de un Switch es necesario crear un recurso de tipo <style>
con la personalización de los atributos asociados.
Por ejemplo, si deseáramos aplicar un color diferente que reemplace a los del tema principal de la aplicación, entonces creamos un estilo cuyo padre sea Widget.MaterialComponents.CompoundButton.Switch
.
Luego aplicamos los colores elegidos en los atributos colorOnSurface
y colorSecondary
.
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.SwitchEnAndroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- ... -->
<item name="switchStyle">@style/Widget.App.Switch</item>
</style>
<style name="Widget.App.Switch" parent="Widget.MaterialComponents.CompoundButton.Switch">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Switch</item>
</style>
<!-- Tema personalizado para Switch-->
<style name="ThemeOverlay.App.Switch" parent="">
<item name="colorOnSurface">@color/lime_900</item>
<item name="colorSecondary">@color/lime_100</item>
</style>
</resources>
Ejemplo De Switch En Android
En los siguientes pasos verás cómo crear una app que cambie el formato de un texto a partir de dos controles switch. El primero activa o desactiva el uso de formato itálico y el segundo activa/desactiva el resaltado del texto.
Si deseas puedes obtener el código desde el siguiente enlace:
Veamos la construcción de esta sencilla app.
Paso 1. Crea un nuevo proyecto en Android Studio llamado «Switch En Android». Selecciona como lenguaje principal a Kotlin, usa la plantilla Empty Activity y nombra a la actividad principal MainActivity
.
Paso 2. Abre el layout main_activity.xml
y modifícalo con la agregación de dos MaterialSwitch
y un TextView
.
Usa el siguiente conjunto de atributos:
- Texto (
user_text
): El texto del usuario posiciónalo en la parte superior del padre - Switch 1 (
switch_italic_format
): Conecta su borde superior sobre el borde inferior del texto. Expándelo horizontalmente - Switch 2 (
switch_highlighted
): Conecta su borde superior con el borde inferior del switch 1. Expandelo horizontalmente
Al terminar tendrás una layout similar al siguiente:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/user_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/user_text"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4"
android:textColor="@color/black"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_italic_format"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/italic_format"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/user_text" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_highlighted"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/highlighted"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.507"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/switch_italic_format" />
</androidx.constraintlayout.widget.ConstraintLayout>
Y en la pestaña de Split verás la prevista así:
Paso 3. Lo siguiente es agregar la lógica de los eventos sobre MainActivity.kt
. Nuestro objetivo es manipular el estilo del texto a partir de escuchar las variaciones en ambos switches, por lo que requeriremos:
- Tomar las referencias de los dos
MaterialSwitch
y elTextView
- Asignar una escucha a switch 1 y aplicar el estilo itálico si está activo, o normal en caso contrario
- Asignar una escucha a switch 2 y cambiar el color del texto a
R.color.green_500
. si está activo, o negro en caso contrario
Teniendo en cuenta estas instrucciones el código XML en la actividad se vería así:
class MainActivity : AppCompatActivity() {
private lateinit var text: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
text = findViewById(R.id.user_text)
setupItalicSwitch()
setupHighlightedSwitch()
}
private fun setupItalicSwitch() {
val italicSwitch: SwitchMaterial = findViewById(R.id.switch_italic_format)
italicSwitch.setOnCheckedChangeListener { _, isChecked ->
val typeface = if (isChecked) Typeface.ITALIC else Typeface.NORMAL
text.setTypeface(null, typeface)
}
}
private fun setupHighlightedSwitch() {
val colorSwitch: SwitchMaterial = findViewById(R.id.switch_highlighted)
colorSwitch.setOnCheckedChangeListener { _, isChecked ->
val colorRes = if (isChecked) R.color.green_500 else R.color.black
text.setTextColor(getColorValue(colorRes))
}
}
private fun getColorValue(@ColorRes colorRes: Int): Int {
return ContextCompat.getColor(this, colorRes)
}
}
Como ves, hemos creado dos método para procesar la preparación de ambos switches desde onCreate()
.
El primero, setupItalicSwitch()
, obtiene la instancia de R.id.switch_italic_format
y luego le asigna la escucha de eventos. Dependiendo del valor de isChecked
, la variable typeface
será asignada con ITALIC
o NORMAL
. Al final se aplica el estilo al texto del usuario con setTypeface()
.
El segundo, setupHighlightedSwitch()
, ejecuta una operación similar, solo que esta vez el valor de isChecked
determina el recurso de color por asignar. Luego se llama a setTextColor()
sobre el texto de usuario.
Salida:
Al correr la aplicación y mover a las palancas de cada switch verás al texto variando entre las dimensiones diseñadas al principio.
Ú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!