Reputation: 639
Does anybody know how to change the size of the default DatePicker in SwiftUI? I have been trying to provide a custom frame to resize the DatePicker but I could't see the expected outcome.
Here is what I tried:
DatePicker("", selection: $currentDate, displayedComponents: .hourAndMinute)
.labelsHidden()
.frame(width: 150, height: 80, alignment: .center)
Upvotes: 14
Views: 14745
Reputation: 2349
This solution didn't work in my case because I am not able to get the width to pass into .frame()
due how my view hierarchy was implementation (scrollviews etc)
Alternatively, I was able to create an extension on DatePicker and override its intrinsicContentSize
var to returned a CGSize with UIView.noIntrinsicMetric
for it's width. Then I was able to use the .fixedSize(horizontal: false, vertical: true)
modifier to resize the Date picker.
The solution above is preferable, IMHO, and this is an alternative approach if the above solution doesn't work with your specific implementation.
extension UIDatePicker {
open override var intrinsicContentSize: CGSize {
CGSize(width: UIView.noIntrinsicMetric,
height: super.intrinsicContentSize.height)
}
}
...
DatePicker("", selection: $selection, displayedComponents: .hourAndMinute)
.datePickerStyle(.wheel)
.labelsHidden()
.fixedSize(horizontal: false, vertical: true)
.frame(alignment: .center)
.padding(.horizontal, 8.0)
Thanks to this article for giving me the Idea for the Extension
Upvotes: 0
Reputation: 2178
While changing the size of the native DatePicker
is still really not possible, it has become easier to build a custom one. In iOS 16.4 Apple introduced .presentationCompactAdaptation
which makes it possible to pop a date popover like the native DatePicker
. This way the hacky work around of the original answer is not necessary anymore.
The following code makes the solution as good as possible downwards compatible.
.popover(isPresented: $showPicker) {
if #available(iOS 16.4, *) {
DatePicker("", selection: $date, displayedComponents: [.date])
.datePickerStyle(.graphical)
.frame(width: 320)
.presentationCompactAdaptation(.popover)
} else if #available(iOS 16.0, *) {
DatePicker("", selection: $date, displayedComponents: [.date])
.datePickerStyle(.graphical)
.frame(width: 320)
.presentationDetents([.medium])
} else {
DatePicker("", selection: $date, displayedComponents: [.date])
.datePickerStyle(.graphical)
.frame(width: 320)
}
}
While this does not directly tackle the issue of changing the size of the SwiftUI DatePicker, it still might be of interest for people who have to work with a SwiftUI DatePicker
.
The only way i found to resize a DatePicker
in SwiftUI was to use the .scaleEffect()
modifier. So the idea was to create my own UI which passes a tap to the DatePicker it covers, which then shows the popover.
For the view to be fully clickable, the DatePicker
has to be scaled to cover the whole width. To dynamically calculate this scale factor between the DatePicker
and the covering UI i used two DatePickers, which i placed behind the covering UI - one two read the native width and one to resize.
The implementation below only scales in the X-Axis since this already achieved what i needed.
struct ScalingDatePicker: View {
@Binding var selection: Date
@State var datepickerSize: CGSize = .zero
let displayComponents: DatePicker.Components = [.date]
static let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
return formatter
}()
var body: some View {
ZStack(alignment: .leading) {
// Hidden DatePicker to grab the Size for calculations
DatePicker("", selection: $selection, displayedComponents: displayComponents)
.background(
GeometryReader { geo in
Color.clear.onAppear {
datepickerSize = geo.size
}
}
)
.allowsHitTesting(false)
.fixedSize()
.opacity(0)
GeometryReader { geo in
DatePicker("", selection: $selection, displayedComponents: displayComponents)
.scaleEffect(
x: geo.size.width/datepickerSize.width,
anchor: .topLeading
)
.labelsHidden()
.frame(maxWidth: .infinity, alignment: .leading)
.padding(6)
}
Text(Self.formatter.string(from: selection))
.frame(maxWidth: .infinity, alignment: .leading)
.padding(12)
.background(Color.white)
.allowsHitTesting(false)
// .opacity(0.5) // -> use this to see the scaling effect in action
.overlay(
RoundedRectangle(cornerRadius: 5)
.strokeBorder(.black)
)
}
.fixedSize(horizontal: false, vertical: true)
}
}
Upvotes: 5
Reputation: 257533
Just clip it at the end as below...
DatePicker("", selection: $currentDate, displayedComponents: .hourAndMinute)
.labelsHidden()
.frame(width: 150, height: 80, alignment: .center)
.clipped()
Upvotes: 14
Reputation: 181
You can change its size using the transform effect , this example will reduce the DatePicker size to be 0.8 of its default size just add this modifier to the picker
DatePicker(......).transformEffect(.init(scaleX: 0.8, y: 0.8))
Upvotes: 7
Reputation: 51
I added .scaleEffect() after the datepicker, and now I can achieve size scaling...
Upvotes: 5
Reputation: 34
The size of the date picker can easily be changed manually. If you go over to Main.storyboard and simply click on the Date Picker, its size can easily be adjusted. However, I am not sure if this is possible with code.
Hope you find this helpful.
Upvotes: -5