Currently the Picker in SwiftUI shows 10 rows of text by default. I would like to have it show only 3.
Context: I am working on a custom DatePicker which uses two Pickers as timeslots for hours and minutes. This is the UI i am trying to achieve (3 rows max per picker).
This is what I currently have (ignore different font and colors, since i have stripped down code for simplicity)
I have attached my code below. Any help would be greatly appreciated, thanks in advance.
TimePickerView.swift
import SwiftUI
struct TimePickerView: View {
@ObservedObject var timeViewModel = TimePickerViewModel()
var numberPressed: ((Date) -> Void)?
var body: some View {
GeometryReader { geo in
VStack(alignment: .center) {
HStack {
Picker("", selection: $timeViewModel.hour) {
ForEach(timeViewModel.hoursArray, id: \.self) { index in
HStack {
Text("\(index < 10 ? "0" : "")\(index)")
.foregroundColor(.green)
.font(.largeTitle)
.padding()
.onTapGesture {
timeViewModel.changeToMinutes = false
}
}
}
}
.pickerStyle(.wheel)
.frame(maxWidth: geo.size.width * 0.4)
.clipped()
.compositingGroup()
Text(":")
.font(.largeTitle)
.foregroundColor(.orange)
Picker("", selection: $timeViewModel.minutes) {
ForEach(timeViewModel.minutesArray, id: \.self) { index in
HStack {
Text("\(index < 10 ? "0" : "")\(index)")
.foregroundColor(.green)
.font(.largeTitle)
.padding()
.onTapGesture {
timeViewModel.changeToMinutes = true
}
}
}
}
.pickerStyle(.wheel)
.frame(maxWidth: geo.size.width * 0.4)
.clipped()
.compositingGroup()
VStack {
Text("AM")
.font(.title2)
.fontWeight(timeViewModel.symbol == "AM" ? .bold : .light)
.foregroundColor(.orange)
.onTapGesture {
timeViewModel.symbol = "AM"
}
Text("PM")
.font(.title2)
.fontWeight(timeViewModel.symbol == "PM" ? .bold : .light)
.foregroundColor(.orange)
.onTapGesture {
timeViewModel.symbol = "PM"
}
}
}
.onChange(of: timeViewModel.selectedDate) { newDate in
self.numberPressed?(newDate)
}
HStack {
Text("hour \(timeViewModel.hour)")
Text("minute \(timeViewModel.minutes)")
Text("\(timeViewModel.symbol)")
}
}
}
}
}
TimePickerViewModel.swift
import Foundation
class TimePickerViewModel: ObservableObject {
@Published var selectedDate = Date()
@Published var hour: Int = 5
@Published var minutes: Int = 5
@Published var changeToMinutes = false
// AM or PM....
@Published var symbol = "AM"
private(set) var hoursArray: [Int] = []
private(set) var minutesArray: [Int] = []
var currentPage = 0
var perPage = 20
init() {
populateHoursAndMinArray()
convertCurrentDateToHourAndMinutes()
}
func convertCurrentDateToHourAndMinutes() {
let date = Date()
let calendar = Calendar.current
hour = calendar.component(.hour, from: date)
minutes = calendar.component(.minute, from: date)
if hour > 11 {
symbol = "PM"
switch hour {
case 13:
hour = 1
case 14:
hour = 2
case 15:
hour = 3
case 16:
hour = 4
case 17:
hour = 5
case 18:
hour = 6
case 19:
hour = 7
case 20:
hour = 8
case 21:
hour = 9
case 22:
hour = 10
case 23:
hour = 11
case 24:
hour = 0
default:
break
}
}
}
func populateHoursAndMinArray() {
for index in 1 ... 12 {
hoursArray.append(index)
}
for index in 0 ... 59 {
minutesArray.append(index)
}
}
}
CodePudding user response:
You can set a maxHeight
to the Picker
s so they would show less number of rows
.frame(maxWidth: geo.size.width * 0.4, maxHeight: 80)