DatePicker(
"Date",
selection: $date,
in: ...Date(),
displayedComponents: [.date]
)
当您选择一个日期(上面的示例10月8日)时,日历仍保留在屏幕上,为了折叠,您需要在其外面点击。
可以在选择日期时自动崩溃吗?
我最终得到了一个相当黑的解决方案,似乎正在完成这项工作。
add aa
@State private var calendarId: Int = 0
用
DatePicker
,.id
和。
.onChange
请注意,该解决方案有一个错误,该错误将导致您更改月或年时删除日历。有关iOS 17解决方案,请参见下面的Tier777的答案。
XCODE 15更新(2023年11月)
在xcode版本上
DatePicker(
"Date", selection: $date, in: ...Date(), displayedComponents: [.date]
)
.id(calendarId)
.onChange(of: date) { _ in
calendarId += 1
})
.onTapGesture
但在Xcode 15中,这似乎导致以下崩溃:this this uitargetedPreview Initializer要求该视图在窗口中,但事实并非如此。修复了这一点,或使用其他实现目标的初始化器。
< 15 you might also need an
.onTapGesture {
calendarId += 1
}
要解决此问题,直到Swiftui带来一些新的更新,我更喜欢将以下解决方案与struct ContentView: View {
@State var calendarId: UUID = UUID()
@State var someday: Date = Date()
var body: some View {
VStack {
DatePicker("Day", selection: $someday, displayedComponents: [.date])
.labelsHidden()
.id(calendarId)
.onChange(of: whatday) { _ in
calendarId = UUID()
}
AnotherView(someday)
}
}
}
explanaiton 使用此解决方案的理解非常重要。我要支持的最小设备是iPhone SE(第三代),它具有屏幕宽度375(您可以像我在按钮操作中一样打印,请检查).popOver
注:在显示日历的地方,您需要确保有足够的高度和宽度空间以显示日历视图框架大小(在我的情况下为365)。在大多数情况下,您不必担心这些事情,这些角案可能只会在小设备中出现。
这只是以上@chris kobrzak之后的更新答案。 我正在使用Xcode 14.1和iOS 15+和16+(iPad和iPhone),并且今天在2022年11月似乎无错误。 我已经看到一些人使用相同的.id()方法抱怨它行不通。 我尚未对此进行测试,但请注意,我正在使用compactdatepickerstyle(),也许在其他样式上也不起作用。 该黑客作品的原因是.id()用于“视图”(datePicker是一个视图)。当您更改视图的ID时,您基本上将其重置(在这种情况下,关闭datePicker)。 有一个很好的解释。
为什么这不是在控制中内置的似乎是个玩笑,但是嘿……
注意,我已经从一个真实的应用程序中删除了以下内容。我已经在愚蠢的文本编辑器中进行了编辑以要在此处发布,以便可能有一些愚蠢的语法错误和原始代码的奇数残余。
import SwiftUI
struct ContentView: View {
@State var selectedDate: Date = .now
@State var showCalendar = false
var body: some View {
VStack {
Button(action: {
print("Display size: \(UIScreen.main.bounds.width)") // For debuging purpose
showCalendar = true // Presenting the Calendar
}, label: {
Image(systemName: "calendar")
Text(selectedDate, style: .date)
})
.popover(isPresented: $showCalendar) {
DatePicker(
"Select date",
selection: $selectedDate,
displayedComponents: .date
)
.datePickerStyle(.graphical)
.padding()
.frame(width: 365, height: 365) // Check the explanation part
.presentationCompactAdaptation(.popover) // It will show popOver in iPhones too
}
.onChange(of: selectedDate) { _, _ in
showCalendar = false // Dismisses the calendar
}
Spacer()
}
}
}
我也有类似的问题,并在我自己的
frame(width: 365, height: 365)
中放了一个
import SwiftUI
struct FooView: View {
@Published var dateOfBirth: Date = Date()
@State private var datePickerId: Int = 0
private var dateOfBirthRange: ClosedRange<Date> {
let dateFrom = Calendar.current.date(byAdding: .year, value: -160, to: Date())!
let dateTo: Date = Date()
return dateFrom...dateTo
}
var body: some View {
Form {
ZStack(alignment: .leading) {
Text("Date of Birth")
.offset(y: -36)
.foregroundColor(Color.accentColor)
.scaleEffect(0.9, anchor: .leading)
DatePicker(
"",
selection: $dateOfBirth,
in: dateOfBirthRange,
displayedComponents: .date
)
.datePickerStyle(CompactDatePickerStyle())
.labelsHidden()
.id(datePickerId)
.onChange(of: dateOfBirth) { _ in
datePickerId += 1
}
}
.padding(.top, 24)
.animation(.default, value: "")
}
}
}
DatePicker
在
this
答案中。 如果您只想在更改一天之后隐藏datepicker。popover
对于我来说,这有效:
struct DatePickerPopover: View {
@State var showingPicker = false
@State var oldDate = Date()
@Binding var date: Date
let doneAction: () -> ()
var body: some View {
Text(date, format:.dateTime.year())
.foregroundColor(.accentColor)
.onTapGesture {
showingPicker.toggle()
}
.popover(isPresented: $showingPicker, attachmentAnchor: .point(.center)) {
NavigationStack {
DatePicker(selection: $date
, displayedComponents: [.date]){
}
.datePickerStyle(.graphical)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
date = oldDate
showingPicker = false
}
}
ToolbarItem(placement: .confirmationAction) {
Button("Done") {
doneAction()
showingPicker = false
}
}
}
}
}
.onAppear {
oldDate = date
}
}
}
为此的简单解决方案是:
DatePicker(
"Date", selection: $date, in: ...Date(), displayedComponents: [.date]
)
.id(calendarId)
.onChange(of: date, perform: { _ in
calendarId += 1
})
答案对我的案件不起作用,也许是因为在我的情况下,不仅有更多的观点。在某些人可能需要的情况下发布此信息:
@State private var date: Date
@State private var calendarId: Int = 0
DatePicker("Select date", selection: $date, in: ...Date(), displayedComponents: .date)
.id(calendarId)
.onChange(of: date) { oldValue, newValue in
let components = Calendar.current.dateComponents([.year, .month], from: oldValue, to: newValue)
guard components.year == 0 && components.month == 0 else {
return
}
calendarId += 1
}