5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Swift5】iOS14のUIDatePickerとUILabelを組み合わせて日付選択ボタンを作る

Last updated at Posted at 2020-11-13

概要

DatePicker だけで日付選択をかっこよく、かつ楽に実装しようとしたところ
デザインがうまいこといかなかった際の試行錯誤を備忘録として残す。
ゴリ押し実装なので軽い気持ちでみてください。

この記事の完成品

日付のラベル部分を押すとカレンダーから日付が選べる
選択が終わるとアニメーションしながら画面が閉じてラベル部分に日付が適応される

やりたかったこと

---年-月-日と表示されている日付をタップするとiOS14のカレンダー式日付選択画面が表示される。
デザインはこんな感じ

選択前

選択後

なんかiOS14からDatePickerの挙動がかっこよくなったのでそれを使えば簡単だろうと思っていました。

iOS14のDatePicker関連の記事はこちら
https://qiita.com/kj_trsm/items/a53b0b3f7e1bc7c06106

Try & Error

1:何も考えずUIButtonを置いてみた

ボタンを置いてデザインを合わせるも、いやいやDatePicker呼べないじゃんってなった(ColorPickerみたいに使うと思ったら違った)
カラーピッカーはこちら
https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204184/3ebb806c-59bf-6dd3-adb9-335026e7101d.jpeg

2:DatePickerを置いてみる

上に書いた記事にもあるが、Styleがいくつかある
今回のデザインに近いであろう

Hoge.swift
datePicker.preferredDatePickerStyle = .compact
datePicker.datePickerMode = .date

見た目はこんな感じ

!

挙動は希望通りなのであとはデザイン調整だ!っという気持ちになるが・・・
デザイン変更が上手いこといかない

  • 背景色のグレーはなんだ? --> datePicker.backgroundColor = .clear にするも、変化なし
  • 文字を左揃えにしたい --> UILabel みたいな設定が見つからない
  • ----年-月-日という形式で表示させるのどうやるの?

解決方法

背景色のグレーはなんだ?

Hoge.swift
datePicker.subviews[0].subviews[0].subviews[0].backgroundColor = .clear

で背景色が変えられた

文字を左揃えにしたい
-> 分からん、無理だった

文字の左揃えができなかったので、ゴリ押しでUILabelの上にUIDatePickerを重ねることに
重ねた上で

Hoge.swift
datePicker.subviews.forEach({ $0.subviews.forEach({ $0.removeFromSuperview() }) })

でdatePickerのSubViewsを消去することで謎のグレー背景も、日付の文字も消える。
重ねた下にあるUILabelの文字を、あたかもUIDatePickerの文字のように表示させる
そうすることでタップ時にはUIDatePickerが動作、表示する日付はUILabelとなり、簡単に希望通りの動作を作れた。

UIDatePicker で ----年-月-日 という形式で表示させるのどうやるの?
-> UILabelに表示させることにしたので調査してません

完成形

StoryboardでUILabelとUIDatePickerを重ねて、UILabelに---年-月-日と設定

HogeViewController.swift

import UIKit
import RxSwift
import RxCocoa

class HogeViewController: UIViewController {

    @IBOutlet var datePicker: UIDatePicker!
    @IBOutlet var dateLabel: UILabel!

    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        datePicker.rx.value.changed.asObservable()
            .subscribe(onNext: { date in
                self.dateLabel.text = date.toDisplayString()
            }
            .disposed(by: disposeBag)
    }

    override func viewDidLayoutSubviews() {
        // datePicker を透明にする
        datePicker.subviews.forEach({ $0.subviews.forEach({ $0.removeFromSuperview() }) })
    }
}

適当にdatePickerの値の変更を監視してUILabelに日付として設定させれば完成
タップしたら値が設定され、閉じる時のアニメーションも勝手にDatePickerがやってくれた

おわりに

結局重ねるというオチになってしまった。
きっともっとちゃんとした解決策がありそうだけど備忘録として残しておきます。

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?