SwiftUI : componente Toggle
Qué es Toggle
El componente Toggle
permite seleccionar un valor entre activado o desactivado. Es un componente equivalente a UISwitch
de UIKit
.
Aquí podéis consultar la documentación oficial
Para crear el componente usaremos uno de los siguientes ‘inicializadores’:
@State var isOn: Bool = false ... Toggle("Option 1", isOn: $isOn)
- ‘Inicializador’ simple que nos proporciona una etiqueta de texto a la izquierda del switch.
@State var isOn: Bool = false ... Toggle(isOn: $isOn) { VStack { Text("This is a") Text("switch") } }
- ‘Inicializador’ que permite personalizar completamente la vista que aparecerá a la izquierda del switch
Nota: el parámetro isOn es una variable de estado que usará el componente Toggle para asignar el valor seleccionado. Cuando queremos usar un valor fijo (por ejemplo, por motivos de pruebas) podemos usar la función .constant(), que pertenece al struct Binding, para cumplir con su implementación sin tener que declarar la variable de estado.
Cómo leer datos de un Toggle
El componente Toggle
necesita que el valor del parámetro isOn
sea una variable de estado de tipo Bool
. Esta variable de estado será la encargada de almacenar el valor actual del componente, y se modificará cuando el usuario interactúe con el Toggle
.
struct ContentView: View { @State var value: Bool = true var body: some View { Group { Toggle("Option 1", isOn: $value) } } }
Por ejemplo: podemos mostrar un texto con el valor actual cuando la variable value
sea mayor que 5
.
struct ContentView: View { @State var value: Bool = false var body: some View { Group { Toggle("Option 1", isOn: $value) if value { Text("Activated!") } }.padding() } }
Modificadores comunes para Toggle
El componente Toggle
comparte los mismos métodos de personalización que el componente View
y pueden ser consultados en el siguiente enlace.
Es muy común usar los siguientes modificadores:
toggleStyle
Permite seleccionar el estilo del Toggle
. Para iOS solo existe la opción SwitchToggleStyle
.
@State var isOn: Bool = false ... Toggle("Option 1", isOn: $isOn) .toggleStyle(SwitchToggleStyle(tint: .red))
Podemos crearnos nuestro propios estilo implementado el protocolo ToggleStyle
.
labelsHidden
Permite ocultar los labels del componente. Es muy útil cuando no queremos mostrar ningún texto, dejándonos posicionar el propio switch a nuestro gusto:
Toggle("Option 1", isOn: $toggle1Value) .labelsHidden()
Como crear un ToggleStyle personalizado
Como hemos indicado anteriormente, el modificador toggleStyle
permite aplicar un estilo al componente Toggle
. Este modificador recibe como parámetro cualquier tipo de dato que implemente el protocolo ToggleStyle
, por lo que vamos a ver que es necesario para implementar este protocolo.
El protocolo ToggleStyle
tiene la siguiente definición en su documentación oficial:
public protocol ToggleStyle { associatedtype Body : View func makeBody(configuration: Self.Configuration) -> Self.Body typealias Configuration = ToggleStyleConfiguration }
Esto quiere decir que debemos implementar el método makeBody
que tiene como parámetro un ToggleStyleConfiguration,
y devolverá un View
. El objeto ToggleStyleConfiguration
tendrá parámetros que podremos usar para controlar el estado actual del Toggle
como, por ejemplo, el parámetro isOn
.
El resultado final es que la vista que se muestre al usuario como Toggle
será lo que devolvamos en este método, por lo que podemos crear una vista completamente diferente o encapsular la propia vista del Toggle
en la que queramos.
Por ejemplo, vamos a añadirle un borde al Toggle
que cambiará de color dependiendo de si está activado o no.
public struct BorderToggleStyle: ToggleStyle { public var tint: Color public func makeBody(configuration: Configuration) -> some View { Group { if configuration.isOn { Toggle(configuration) .toggleStyle(SwitchToggleStyle(tint: tint)) .padding() .overlay( RoundedRectangle(cornerRadius: 10) .stroke(tint, lineWidth: 1) ) } else { Toggle(configuration) .toggleStyle(SwitchToggleStyle(tint: tint)) .padding() .overlay( RoundedRectangle(cornerRadius: 10) .stroke(Color.gray, lineWidth: 1) ) } } } }
Esta clase que implementa el protocolo ToggleStyle
nos permite controlar si está activo o no a través de la propiedad configuration.isOn
. De esta forma podemos devolver una vista de Toggle
con el borde de diferente color para conseguir el efecto deseado.
Para usar el estilo BorderToggleStyle
solo tendremos que ‘setearlo’ en el propio Toggle
:
struct ContentView: View { @State var value: Bool = true var body: some View { Group { Toggle("Option 3", isOn: $value) .toggleStyle(BorderToggleStyle(tint: .blue)) } } }
También podemos conseguir un estilo parecido a un checkbox de una manera muy sencilla:
public struct CheckToggleStyle: ToggleStyle { public func makeBody(configuration: Configuration) -> some View { HStack() { configuration.label .frame(maxWidth: .infinity, alignment: .leading) Button(action: { configuration.isOn.toggle() }, label: { Group { if configuration.isOn { Image("check-box-on") .resizable() .scaledToFit() } else { Image("check-box-off") .resizable() .scaledToFit() } } .frame(width: 25, height: 25) }) .frame(width: 44, height: 44) } } }
En este caso también estamos usando la propiedad configuration.label
que contiene la vista de texto que aparece a la izquierda del componente Toggle
.
También estamos creando un botón que se comportará como un Toggle
modificando el parámetro configuration.isOn
entre true
y false
, y controlando que imagen se debe mostrar.
Hemos usado las siguientes imágenes para este ejemplo:
Ejemplo
Estos son algunos ejemplos de personalización que podemos llegar a montar en cualquier tipo de vista personalizada que funcione como un Toggle
y sea de esta forma.
Puedes encontrar este ejemplo en github.com bajo el apartado Toggle.
Rafael Fernández,
iOS Tech Lider