Search code examples
swiftuiuipickerviewxcode13

How do I style Text in SwiftUI Picker View?


I have a time picker in SwiftUI and any modification that I apply to the Text values in the picker are ignored. How do I do this correctly? I am using Xcode 13 on Big Sur.

Here is the result without any modification:

Timer picker

I want the times to be larger and white so I added .font() and .foregroundColor() modifiers. Here is my code:

struct TimerPicker: View {
    @Binding var customTime: CustomTime
    
    var body: some View {
        GeometryReader { geometry in
            HStack (spacing: 0.0){
                VStack {
                    Picker(selection: self.$customTime.selectedHour, label: Text("Hrs")) {
                        ForEach(0..<24) { hour in
                            Text("\(hour) hrs")
                                .foregroundColor(.white)
                                .font(.title3)
                        }
                    }
                }
                .frame(width: geometry.size.width * 0.33)
                .clipped()
                
                VStack {
                    Picker(selection: self.$customTime.selectedMin, label: Text("Min")) {
                        ForEach(0..<61) { min in
                            Text("\(min) min")
                                .foregroundColor(.white)
                                .font(.title3)
                        }
                    }
                }
                .frame(width: geometry.size.width * 0.33)
                .clipped()
                
                VStack {
                    Picker(selection: self.$customTime.selectedSecond, label: Text("Sec")) {
                        ForEach(0..<61) { sec in
                            Text("\(sec) sec")
                                .foregroundColor(.white)
                                .font(.title3)
                        }
                    }
                }
                .frame(width: geometry.size.width * 0.33)
                .clipped()
                .transition(.scale)
            }
        } //: Geometry
    }
}

There is no change in the styling of the picker values. What is the correct way to do this?


Solution

  • Your code seems to work for me, although I made the following small modifications. This is the code that works for me: (note there is no 60 min or 60 sec)

    import SwiftUI
    
    @main
    struct TestApp: App {
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
    
    struct ContentView: View {
        @State var customTime = CustomTime()
        
        var body: some View {
            Spacer()
            TimerPicker(customTime: $customTime)
            Spacer()
        }
    }
    
    struct CustomTime: Identifiable, Hashable {
        let id = UUID()
        var selectedHour = 0
        var selectedMin = 0
        var selectedSecond = 0
    }
    
    struct TimerPicker: View {
        @Binding var customTime: CustomTime
        
        var body: some View {
            GeometryReader { geometry in
                HStack (spacing: 0.0){
                    VStack {
                        Picker(selection: $customTime.selectedHour, label: Text("Hrs")) {
                            ForEach(0..<24) { hour in
                                Text("\(hour) hrs").tag(hour) // <--- tag
                                    .foregroundColor(.white)
                                    .font(.title3)
                            }
                        }
                    }
                    .frame(width: geometry.size.width * 0.33)
                    .clipped()
                    
                    VStack {
                        Picker(selection: $customTime.selectedMin, label: Text("Min")) {
                            ForEach(0..<60) { min in  // <--- only to 59
                                Text("\(min) min").tag(min) // <--- tag
                                    .foregroundColor(.white)
                                    .font(.title3)
                            }
                        }
                    }
                    .frame(width: geometry.size.width * 0.33)
                    .clipped()
                    
                    VStack {
                        Picker(selection: $customTime.selectedSecond, label: Text("Sec")) {
                            ForEach(0..<60) { sec in  // <--- only to 59
                                Text("\(sec) sec").tag(sec) // <--- tag
                                    .foregroundColor(.white)
                                    .font(.title3)
                            }
                        }
                    }
                    .frame(width: geometry.size.width * 0.33)
                    .clipped()
                    .transition(.scale)
                }
                .pickerStyle(.wheel)    // <--- here
                .background(Color.red)  // <--- here
            } //: Geometry
        }
    }