はじめに
いつかやってみたかったハーフモーダルの実装、
ドキュメントや記事を見る限り、思ったより簡単?そうに思えたのでやってみました。
整理
モーダルの表示
表示: 親画面.present(子画面:animated:completion:)
遷移スタイル: UIModalTransitionStyle.coverVertical
※デフォルト
表示スタイル: UIModalPresentationStyle.automatic
※デフォルト
👉 子画面.modalPresentationStyle = .popover
に変更する
モーダルの設定
UISheetPresentationController
を取得、detents
を変更する
ポップオーバー:子画面.popoverPresentationController
シート:ポップオーバー.adaptiveSheetPresentationController
ディテント(戻り止め): UISheetPresentationController.detents = [.large()]
※デフォルト
👉 シート.detents = [.medium(), .large()]
に変更してハーフモーダル可にする
👉 シート.detents = [.medium()]
ハーフモーダルのみの場合
条件により詳細設定
■ ハーフモーダル表示中に子画面自体をスクロールさせる(フルモーダル化はエッジ引き上げ)
👉シート.prefersScrollingExpandsWhenScrolledToEdge = false
にする
■ 特定のイベント後にハーフモーダルにする場合👉
シート.animateChanges {
シート.selectedDetentIdentifier = .medium
}
■ ハーフモーダル表示中に親画面も操作可能にさせる
👉シート.largestUndimmedDetentIdentifier = .medium
にする
■ (デバイス横向き時など)モダールが画面いっぱいに表示され困る場合
👉シート.prefersEdgeAttachedInCompactHeight = true
にする
※デフォルトはfalse
さらに横幅を指定したい場合は、
シート.widthFollowsPreferredContentSizeWhenEdgeAttached = true
※デフォルトはfalse
にすることで子画面.preferredContentSize
の値でカスタマイズできる
■ 他にもモーダルの角を丸くしたり、上部につまみを付けたりできる
角の丸み: シート.preferredCornerRadius = 20.0
※デフォルトはnil
つまみ: シート.prefersGrabberVisible = true
※デフォルトはfalse
モーダルのクローズ
クローズ: dismiss(animated:completion:)
実装
親画面でモーダル表示の設定を行う
func showHalfModal() {
let storyboard = UIStoryboard(name: "HalfModal", bundle: nil)
let vc = storyboard.instantiateViewController(identifier: "HalfModal")
guard let modalVC = vc as? HalfModalViewController else { return }
modalVC.delegate = self
// スタイルをポップオーバーに設定
modalVC.modalPresentationStyle = .popover
if let popover = modalVC.popoverPresentationController {
// iOS 15.0から設定可能なので
if #available(iOS 15.0, *) {
let sheet = popover.adaptiveSheetPresentationController
// ハーフモーダルのみに設定
sheet.detents = [.medium()]
// 以下オプションの設定
sheet.prefersScrollingExpandsWhenScrolledToEdge = false
sheet.prefersEdgeAttachedInCompactHeight = true
sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
}
}
// モーダル表示
self.present(modalVC, animated: true)
}
公式ドキュメント書き方はこんな感じでviewController
から直接sheet
を取ってた
func showMyViewControllerInACustomizedSheet() {
let viewControllerToPresent = MyViewController()
if let sheet = viewControllerToPresent.sheetPresentationController {
sheet.detents = [.medium(), .large()]
sheet.largestUndimmedDetentIdentifier = .medium
sheet.prefersScrollingExpandsWhenScrolledToEdge = false
sheet.prefersEdgeAttachedInCompactHeight = true
sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
}
present(viewControllerToPresent, animated: true, completion: nil)
}
感想
実装が簡単で感動しました。
実際に個人開発中のアプリでハーフモーダルを実装していじってみましたが、操作性がアップした気がします。
今後は可能な限りハーフモーダル(もしくはハーフ&フル)に切り替えていこうと思います。
参考記事