SwiftUI: componente Picker
Qué es Picker
El componente Picker
permite al usuario seleccionar un valor entre un listado de opciones definido. Es un componente equivalente a UIPickerView
y UISegmentedControl
de UIKit
.
Aquí podéis consultar la documentación oficial
La creación del componente se puede realizar de varias formas:
struct ContentView: View { let items = ["Sevilla", "Cádiz", "Huelva", "Córdoba", "Málaga", "Granada", "Jaén", "Álmería"] @State private var selection: String = "Sevilla" var body: some View { Picker("Select one option", selection: $selection) { ForEach(items, id: .self) { Text("($0)") .foregroundColor(.blue) } } } }
Esteinit
consta de los siguientes parámetros:
String
: texto a mostrar para introducir alPicker
. En este ejemplo no se verá, ya que se usa en casos específicos como cuando lo incluimos en unNavigationView
→Form
.selection
: variable de estado con la selección actual delPicker
.content
: es el listado de opciones que se presentarán en el picker.
También disponemos de otro init
que nos da el mismo resultado:
struct ContentView: View { let items = ["Sevilla", "Cádiz", "Huelva", "Córdoba", "Málaga", "Granada", "Jaén", "Álmería"] @State private var selection: String = "Sevilla" var body: some View { Picker(selection: $selection, label: Text("Select one option")) { ForEach(items, id: .self) { Text("($0)") .foregroundColor(.blue) } } } }
En este caso tenemos los siguientes parámetros:
selection
: variable de estado con la selección actual delPicker
.label
:View
a mostrar para introducir alPicker
. En este ejemplo no se verá, ya que se usa en casos específicos como cuando lo incluimos en unNavigationView
→Form
.content
: es el listado de opciones que se presentarán en el picker.
Nota: el parámetro selection es una variable de estado que usará el componente Picker 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 cargar y leer datos de un Picker
Para poder saber qué opción es la que está seleccionada en un Picker
tenemos que crear una relación entre los datos cargados y la variable selection
.
La carga de datos de un Picker
se realizará normalmente a través del componente ForEach
, iterando sobre un listado de elementos. En este punto lo importante es que cada elemento del ForEach
sea único porque implementa el protocolo Identifiable
o porque lo especificamos explicitamente en el ForEach
(cómo cuando cargamos un listado de String
e indicamos id: .self
).
Al realizar la carga de esta forma el Picker
es capaz de identificar cada elemento de forma única y lo que hace es volcar la selección actual en la variable selection
que recibe en su init.
Por este motivo, la variable selection deberá ser del mismo tipo que el id
que usamos en el ForEach
. Para una lista de String
la variable de estado será String
y tiene que tener uno de los valores preseleccionados (no puede ser opcional ?
).
let items = ["Sevilla", "Cádiz", "Huelva", "Córdoba", "Málaga", "Granada", "Jaén", "Álmería"] @State private var selection: String = "Sevilla"
En los ejemplos anteriores esta variable es de tipo String
porque el id
del ForEach
es la misma variable sobre la que se itera (un String
), pero puede ser cualquier otro tipo:
struct ContentView: View { @State private var selection: Flavor = Flavor.chocolate var body: some View { VStack { Picker(selection: $selection, label: Text("Select one option")) { ForEach(Flavor.allCases, id: .self) { Text("($0.rawValue)") .foregroundColor(.orange) } } Text("Selection: (selection.rawValue)") } } enum Flavor: String, CaseIterable, Identifiable { case chocolate = "Chocolate" case vanilla = "Vanilla" case strawberry = "Strawberry" var id: String { self.rawValue } }
Modificadores comunes para Picker
El componente Picker
comparte los mismos métodos de personalización que el componente View
, y pueden ser consultados en el siguiente enlace.
pickerStyle
Permite alternar entre diferentes modos de presentación del Picker
. El parámetro debe implementar el protocolo PickerStyle
.
struct ContentView: View { @State private var selection: Flavor = Flavor.chocolate var body: some View { ScrollView { VStack { Group { Picker("Select one option", selection: $selection1) { ForEach(Flavor.allCases, id: .self) { Text("($0.rawValue)") .foregroundColor(.blue) } } .pickerStyle(WheelPickerStyle()) Text("Selection: (selection1.rawValue)") } } } .padding() } enum Flavor: String, CaseIterable, Identifiable { case chocolate = "Chocolate" case vanilla = "Vanilla" case strawberry = "Strawberry" var id: String { self.rawValue } } }
Para iOS existen diferentes implementaciones:
WheelPickerStyle
Este tipo es equivalente a UIPickerView
de UIKit
. Es el tipo por defecto.
.pickerStyle(WheelPickerStyle())
SegmentedPickerStyle
Este tipo es equivalente a UISegmentedControl
de UIKit.
.pickerStyle(SegmentedPickerStyle())
MenuPickerStyle
(iOS 14)
.pickerStyle(MenuPickerStyle())
InlinePickerStyle
(iOS 14)
.pickerStyle(InlinePickerStyle())
Ejemplo
Puedes encontrar este ejemplo en github.com bajo el apartado Picker.
Rafael Fernández,
iOS Tech Lider