问题
I have created a custom DatePicker using UIDatePicker
and when I select the field it displays the date and time as an option at the bottom of the screen without going directly to the pop-up. Not sure how to describe it so please see the image below:
Please see my code below:
import SwiftUI
struct CustomDateTimePicker: View {
@State private var date: Date?
@State private var time: String? = "Time"
var body: some View {
HStack {
Image("Time")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 22.0, height: 22.0, alignment: .center)
DateField("", date: self.$date)
.font(.system(size: 19, weight: .light, design: .rounded))
.foregroundColor(Color.gray)
}.padding()
.frame(width: 200, height: 100)
.background(Color.white)
.cornerRadius(8)
.shadow(color: Color.black.opacity(0.1), radius: 30, x: 0 , y: 15)
}
}
class DateTextField: UITextField {
// MARK: - Public properties
@Binding var date: Date?
// MARK: - Initializers
init(date: Binding<Date?>) {
self._date = date
super.init(frame: .zero)
if let date = date.wrappedValue {
self.datePickerView.date = date
}
self.datePickerView.addTarget(self, action: #selector(dateChanged(_:)), for: .valueChanged)
self.inputView = datePickerView
self.tintColor = .clear
self.font = UIFont.systemFont(ofSize: 18.0, weight: .medium)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Private properties
private lazy var datePickerView: UIDatePicker = {
let datePickerView = UIDatePicker()
datePickerView.datePickerMode = .dateAndTime
datePickerView.minuteInterval = 5
if #available(iOS 14.0, *) {
datePickerView.preferredDatePickerStyle = .compact
datePickerView.sizeToFit()
} else {
datePickerView.preferredDatePickerStyle = .wheels
}
return datePickerView
}()
// MARK: - Private methods
@objc func dateChanged(_ sender: UIDatePicker) {
self.date = sender.date
}
}
struct DateField: UIViewRepresentable {
// MARK: - Public properties
@Binding var date: Date?
// MARK: - Initializers
init<S>(_ title: S, date: Binding<Date?>, formatter: DateFormatter = .yearMonthDay) where S: StringProtocol {
self.placeholder = String(title)
self._date = date
self.textField = DateTextField(date: date)
self.formatter = formatter
}
// MARK: - Public methods
func makeUIView(context: UIViewRepresentableContext<DateField>) -> UITextField {
textField.placeholder = placeholder
return textField
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<DateField>) {
if let date = date {
uiView.text = formatter.string(from: date)
}
}
// MARK: - Private properties
private var placeholder: String
private let formatter: DateFormatter
private let textField: DateTextField
}
extension DateFormatter {
static var yearMonthDay: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "dd MMM yyyy HH:mm"
return formatter
}
}
struct CustomDateTimePicker_Previews: PreviewProvider {
static var previews: some View {
CustomDateTimePicker()
}
}
How can I have the compact menu be shown when after clicking on my field instead of having to choose the date/time at the bottom?
回答1:
With the Compact DatePicker you can't automatically show the calendar without selecting it from the part that show up at the bottom. Open UIDatePicker programmatically in iOS 14
You can (if the 5 minute interval isn't a requirement) use GraphicalDatePickerStyle
which shows a very similar calendar.
struct ParentDatePicker: View {
@State var showGraphical: Bool = false
@State var currentDate: Date = Date()
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "dd MMM yyyy HH:mm"
return formatter
}
var body: some View {
Button(action: {
showGraphical.toggle()
}, label: {
Label(
title: { Text("\(currentDate, formatter: dateFormatter)") },
icon: { Image(systemName: "clock") })
})
.padding()
.frame(width: 200, height: 100)
.background(Color.white)
.cornerRadius(8)
.shadow(color: Color.black.opacity(0.1), radius: 30, x: 0 , y: 15)
.sheet(isPresented: $showGraphical, content: {
CusDatePicker(currentDate: $currentDate)
})
}
}
struct CusDatePicker: View {
@Binding var currentDate: Date
var body: some View {
//https://developer.apple.com/documentation/swiftui/datepicker
DatePicker("Date", selection: $currentDate, displayedComponents: [.date, .hourAndMinute])
//.datePickerStyle(CompactDatePickerStyle())
.datePickerStyle(GraphicalDatePickerStyle())
}
}
struct CusDatePicker_Previews: PreviewProvider {
static var previews: some View {
ParentDatePicker()
}
}
来源:https://stackoverflow.com/questions/65384408/swiftui-uidatepicker-compact-doesnt-go-directly-to-pop-up