UIDatePickerですがiOSから下のようなカレンダー形式が使えるようになりました。
コードは下のとおりです。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let datePicker = UIDatePicker() datePicker.preferredDatePickerStyle = .inline datePicker.center = view.center view.addSubview(datePicker) } }
こちらですが下のようにwidthを広げてしまうと曜日や時間の部分が潰れるという問題があります。
今回はこれを解消するためにsystemLayoutSizeFittingというメソッドを使って正しい高さをセットしてみようと思います。
datePicker.frame.size.width = view.frame.width
systemLayoutSizeFittingとはUIViewのメソッドで、引数に合うSizeを返してくれます。
下のように引数に自身のViewのWidthを入れ、横の優先順位を上げる(defaultHighをセットする)ことで横幅いっぱいの時用のサイズを取得できます。
let targetSize = CGSize(width: view.frame.width, height: 0) let size = datePicker.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow) → (390.0, 397.3333333333333)
あとはdatePickerに取得したsizeをセットすれば曜日や時間部分が潰れなくなります。
datePicker.frame.size = size
datePickerModeを変更した場合、それにあった数字を計算してくれます。
print(datePicker.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)) // → (390.0, 397.3333333333333) datePicker.datePickerMode = .date print(datePicker.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)) // → (390.0, 365.0)
ちなみにカレンダー形式UIDatePickerの正しい高さはiOS15とiOS14で微妙に違います。
下がiOS14で高さを計測した時の数字です。
このようにOSのバージョンによって微妙にずれがあるのでできるだけsystemLayoutSizeFittingを使って計算するのが良いかと思います。
print(datePicker.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)) // → (390.0, 405.6666666666667) datePicker.datePickerMode = .date print(datePicker.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)) // → (390.0, 368.3333333333333)
ただsystemLayoutSizeFittingは既にDatePickerのサイズが違う状態では違う値になるので注意が必要です。
下のようにviewDidAppearでsystemLayoutSizeFittingを取得し直したらtargetSizeより大きいWidthになってしまいました。
もしviewDidAppear時点でDatePickerのWidthが初期値(320)だと正しい数字が取れるようです。
class ViewController: UIViewController { let datePicker = UIDatePicker() override func viewDidLoad() { super.viewDidLoad() datePicker.preferredDatePickerStyle = .inline let targetSize = CGSize(width: view.frame.width, height: 0) datePicker.datePickerMode = .date let size = datePicker.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow) datePicker.frame.size = size datePicker.center = view.center view.addSubview(datePicker) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let targetSize = CGSize(width: view.frame.width, height: 0) print(datePicker.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)) // → (407.0, 377.0) } }