I build a iOS 14 DatePicker. When I selected a date from the picker, it some date in format 27 Dec 2020 and some date show in format 26/12/2020. May I know what is the problem and how can I make it consistent?
struct ContentView : View {
#State private var birthDate = Date()
var body: some View {
VStack(alignment: .leading){
DatePicker(selection: $birthDate, in: Date()..., displayedComponents: .date){
Text("Date")
}
}.padding()
}
}
Related
Is there a way to get a DatePicker that has been expanded to contract when the user clicks on a date?
The following code will crash the app - or at least put it into the locked state.
There is a Text component showing the date. When you click on it the DatePicker appears in its place - but there is no way to dismiss it after it is an expanded mode. Trying to swap back to the original Text, by setting edit mode to false when the date changes effectively locks the app:
struct ContentView: View {
#State private var date: Date = .now
#State private var editMode: Bool = false
var body: some View {
VStack {
if editMode {
DatePicker("Test", selection: $date)
.labelsHidden()
.onChange(of: date) { _ in
editMode = false
}
.frame(width: 50)
} else {
Text(date.formatted(date: .abbreviated, time: .omitted))
.onTapGesture {
editMode = true
}
}
}
.padding()
}
}
Ideally I'd also be able to dismiss it programatically.
I have tried using a ZStack with opacity control, such as:
struct ContentView: View {
#State private var date: Date = .now
#State private var editMode: Bool = false
var body: some View {
ZStack {
DatePicker("Test", selection: $date)
.labelsHidden()
.onChange(of: date) { _ in
editMode = false
}
.frame(width: 50)
.opacity(editMode ? 1.0 : 0.0)
Text(date.formatted(date: .abbreviated, time: .omitted))
.onTapGesture {
editMode = true
}
.opacity(editMode ? 0.0 : 1.0)
}
.padding()
}
}
But this isn't working in my actual use case. I'd really like to know if there was a way of dismissing that DatePicker expanded form.
I have a date-picker in my app, which only selects the date, not the time. Looks like this:
DatePicker("Birthday",
selection: $date,
displayedComponents: [.date])
A date picker gives you a date object to work with. So, when the user selects a date, it of course also comes with a time, timezone, etc. My problem is, that the time is set to the current time by default. However, I need it to be set to midnight always. How can I provide a default value?
A possible solution that came to my mind was using a formatter and storing the date as a String (instead of a Date), but since I need to do some work with it later (e.g. calculate days between two dates), this doesn't seem like the best approach to me.
you could try this:
struct ContentView: View {
#State var date = Date()
var body: some View {
VStack {
Text("\(date)")
DatePicker("Birthday", selection: $date, displayedComponents: [.date])
.onChange(of: date) { newDate in
if let midnight = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: newDate) {
date = midnight
}
}
}
}
}
or this:
struct ContentView: View {
#State var date = Date()
var body: some View {
VStack {
Text("\(date)")
DatePicker("Birthday", selection: $date, displayedComponents: [.date])
}
.onAppear {
if let midnight = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date()) {
date = midnight
}
}
}
}
or this:
struct ContentView: View {
#State var date = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date())!
var body: some View {
VStack {
Text("\(date)")
DatePicker("Birthday", selection: $date, displayedComponents: [.date])
}
}
}
How to Change GraphicalDatePickerStyle Date picker text color and Selection Colour:-
Code:-
DatePicker("Time",selection: dateProxy,displayedComponents: [.hourAndMinute])
.datePickerStyle(GraphicalDatePickerStyle())
.accentColor(.white)
.labelsHidden()
Output:-
But I want to achieve DatePicker given below, is it possible in GraphicalDatePickerStyle Style or not?
Try to Achieve:-
Seems like you are looking for the dark mode picker! Just apply the dark colorScheme to the component:
DatePicker("Time", selection: $date, displayedComponents: [.hourAndMinute])
.datePickerStyle(GraphicalDatePickerStyle())
.background(Color.black)
.environment(\.colorScheme, .dark) // <- This modifier
Result:
🌈 Apply color
Also, you can apply the colorMultiply modifier for coloring the picker in a pleasant way:
Demo Full Code
struct ContentView: View {
#State private var date = Date()
var colors: [Color] = [.white, .gray, .red, .green, .blue, .orange, .yellow, .pink, .purple] // <- You can use any color! This is just for demonstrate
var body: some View {
VStack {
ForEach(colors, id:\.self) { color in
DatePicker("Time", selection: $date, displayedComponents: [.hourAndMinute])
.datePickerStyle(GraphicalDatePickerStyle())
.background(Color.black.grayscale(1))
.colorMultiply(color) // <- This line does the trick
.environment(\.colorScheme, .dark) // <- Don't Forget this
}
}
}
}
This works for macOS 11 and iOS 14 (Xcode 12 beta 3)...
1.Take the Label out of the DatePicker - I've left it commented out here so its obvious to readers that the Label should be taken out of the DatePicker View.
Place the DatePicker in an HStack (or other ViewBuilder.
Add a Label for the DatePicker in the HStack.
Use the .colorMultiplier view modifier to change the color of the DatePicker date and time "button".
In this particular example I am also changing the colour of the date and time "button" depending on whether the binding value in the date picker is nil.
let now = Date()
HStack {
Text("Date")
DatePicker(selection: Binding($observedObject.date, replacingNilWith: now)) {
// Text("Date")
// .foregroundColor(Color(.label))
}
.colorMultiply(observedObject.date == nil ? Color(.placeholderText) : Color(.label))
}
Also I'm using an extension to Binding in this example which is something I use throughout my core data projects.
public extension Binding where Value: Equatable {
init(_ source: Binding<Value?>, replacingNilWith nilProxy: Value) {
self.init(
get: { source.wrappedValue ?? nilProxy },
set: { newValue in
if newValue == nilProxy {
source.wrappedValue = nil
}
else {
source.wrappedValue = newValue
}
})
}
}
As always full credit to Alan Quatermain for this extension to Binding.
Closest I got:
Group {
DatePicker("Time",selection: $dateProxy, displayedComponents: [.hourAndMinute])
.datePickerStyle(GraphicalDatePickerStyle())
.accentColor(.black)
.colorInvert()
.labelsHidden()
.padding()
}
.background(Color.black.opacity(0.8))
does anyone know how to give the minutes DatePicker an interval? I am trying to only display multiples of 15 (0, 15, 30, 45). Is this only yet possible by interfacing with UIKit?
I believe it's not using the in: ...Date() part, at least I couldn't think of a solution. Here is my snippet:
DatePicker(
"",
selection: $selectedDate,
/*in: ...Date(),*/
displayedComponents: .hourAndMinute
)
Thanks so much!
The solution is to configure using UIDatePicker.appearance before SwiftUI DatePicker is created.
Tested with Xcode 13.3 / iOS 15.4
Main part is:
UIDatePicker.appearance().minuteInterval = 15
Complete code in here
can be tried this way:
struct DatePickerView: View {
#Binding var dateSelected: Date
var type: DatePickerComponents? = .date
var body: some View {
DatePicker("", selection: $dateSelected, displayedComponents: .hourAndMinute)
.datePickerStyle(.wheel)
.onAppear {
if type == .hourAndMinute {
UIDatePicker.appearance().minuteInterval = 15
} else {
UIDatePicker.appearance().minimumDate = dateSelected
}
}
}
}
What about using two pickers, one for hour and one for minute, and then converting to Date() afterwards? It's not pretty but this gets part of the way there:
struct ContentView: View {
#State private var hour = 1
#State private var minute = 0
let minutes = [0, 15, 30, 45]
var body: some View {
GeometryReader { geometry in
HStack {
Picker("Hour", selection: self.$hour) {
ForEach(1...12, id: \.self) {
Text("\($0)")
}
}
.labelIsHidden()
.frame(maxWidth: geometry.size.width / 4)
.clipped()
Picker("Minutes", selection: self.$minute) {
ForEach(self.minutes, id: \.self) { minute in
Text(minute == 0 ? " : 0\(minute)" : " : \(minute)")
}
}
.labelIsHidden()
.frame(maxWidth: geometry.size.width / 4)
.clipped()
}
}
}
}
I´ve created a DatePicker element in SwiftUI, but the DatePicker opens inside the view instead of a sheet at the bottom. (Screenshot below)
My code:
#ObservedObject private var report = Report(
id: 0,
timestamp: Date(timeIntervalSinceReferenceDate: 118800),
date: Date(timeIntervalSinceReferenceDate: 118800),
)
Section(header: Text("Allgemeine Daten")) {
HStack {
Label(string: "Name")
Divider()
TextField("Name", text: $person.name)
}
HStack {
Label(string: "Monat")
Divider()
DatePicker(selection: $report.date, displayedComponents: .date) {
Text("Select a date")
}
}
}
The Section is inside a NavigationView and Form. What could be the issue?
This is because it's actually getting temporarily added to the view hierarchy where your DatePicker is. Since your date picker is in an HStack, it gets appended to the end of the HStack resulting in what you see. If you add the DatePicker by itself, then it gets added to the Section instead, and will shift content below. It's still a pretty terrible animation/user experience, though, so I have to assume it's a bug.