bona912
bona912

Reputation: 639

How to change the size of DatePicker?

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

Answers (6)

TMin
TMin

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

Deitsch
Deitsch

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)
    }
}

Old answer

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

Asperi
Asperi

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

Rasheed
Rasheed

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

icebarley
icebarley

Reputation: 51

I added .scaleEffect() after the datepicker, and now I can achieve size scaling...

Upvotes: 5

natasha
natasha

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

Related Questions