SwiftUI UIDatePicker .compact doesn't go directly to pop-up

ぐ巨炮叔叔 提交于 2021-01-29 20:48:42

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!