Picker / Segmented Control - SwiftUI
Updated for iOS 15
Segmented control
SwiftUI’s Picker
can also be used to create segmented controls equivalent to UISegmentedControl
from UIKit, although it needs to be bound to some state and you must ensure to give each segment a tag so it can be identified. Segments can be text or pictures; anything else will silently fail. Example:
struct ContentView: View {
@State private var favoriteColor = "Red"
var colors = ["Red", "Green", "Blue"]
var body: some View {
VStack {
Picker("What is your favorite color?", selection: $favoriteColor) {
ForEach(colors, id: \.self) {
Text($0)
}
}
.pickerStyle(.segmented)
Text("Value: \(favoriteColor)")
}
}
}
Picker
Date picker
SwiftUI gives us a dedicated picker type called DatePicker
that can be bound to a date property. Yes, Swift has a dedicated type for working with dates, and it’s called – unsurprisingly – Date
.
struct ContentView: View { @State private var wakeUp = Date() // when you create a new Date instance it will be set to the current date and time let now = Date() // create a second Date instance set to one day in seconds from now let tomorrow = Date().addingTimeInterval(86400) var body: some View { VStack{ DatePicker("Please enter a time", selection: $wakeUp, displayedComponents: .hourAndMinute) DatePicker("Please enter a date", selection: $wakeUp, in: Date()...) .labelsHidden() } } }
Multi-Component Picker
Screenshot
import SwiftUI struct ContentView: View { @State var data: [(String, [String])] = [ ("One", Array(0...10).map { "\($0)" }), ("Two", Array(20...40).map { "\($0)" }), ("Three", Array(100...200).map { "\($0)" }) ] @State var selection: [String] = [0, 20, 100].map { "\($0)" } var body: some View { VStack(alignment: .center) { Text(verbatim: "Selection: \(selection)") MultiPicker(data: data, selection: $selection).frame(height: 300) } } } struct MultiPicker: View { typealias Label = String typealias Entry = String let data: [ (Label, [Entry]) ] @Binding var selection: [Entry] var body: some View { GeometryReader { geometry in HStack { ForEach(0..<self.data.count) { column in Picker(self.data[column].0, selection: self.$selection[column]) { ForEach(0..<self.data[column].1.count) { row in Text(verbatim: self.data[column].1[row]) .tag(self.data[column].1[row]) } } .pickerStyle(WheelPickerStyle()) .frame(width: geometry.size.width / CGFloat(self.data.count), height: geometry.size.height) .clipped() } } } } }