来月にはiOS15が正式リリースされると思いますが、今回はiOS15にてハーフモーダルが実装可能になったので使い方を紹介したいと思います。
ViewControllerを作成し、対応するStoryboardでボタンをタップしたらmodalを出すシンプルな画面を用意します。ハーフモーダルで表示した時にわかりやすいように上詰で色をつけたviewを3つ表示しています。
ハーフモーダルを扱うには、iOS15で追加されたsheetPresentationControllerを使用します。準備したViewControllerのprepare内で設定したいと思います。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let next = segue.destination if let sheet = next.sheetPresentationController { sheet.detents = [.medium()] } }
これでボタンをタップするとこのように表示されます。
detentsとはモーダルの高さの指定で、現在公式ではmediumとlargeが用意されており、mediumを指定することでハーフモーダルが表示されます。
デフォルトの値はlargeが指定されており、largeは今までのモーダルと同じ高さになります。
detentsは配列になっており、
sheet.detents = [.medium(), .large()]
上記の様に指定することで、モーダルをスワイプ操作することでmediumとlargeを切り替えられます。
また、モーダル初期表示の高さは配列の先頭に指定した物で表示されるので、[.medium(), .large()]にすればハーフモーダルが初期表示の高さになり、[.large(), .medium()]なら全画面表示が初期表示になります。
スワイプ操作でmediumとlargeを切り替えられますが、ボタンや入力の状況などでコードで高さを切り替えたい時は以下の様にします。
if let sheet = self.sheetPresentationController { sheet.selectedDetentIdentifier = .medium }
ただし、このままだとアニメーション無しで切り替わるので、アニメーションを行う場合は以下の様にanimateChangesを使用します。
if let sheet = self.sheetPresentationController { sheet.animateChanges { sheet.selectedDetentIdentifier = .medium } }
今回のサンプルのようなコンテンツをハーフモーダルで表示する場合にスクロールを使用すると思うのですが、初期設定だと、モーダル内のどこをスワイプしてもモーダルが動いてしまい、スクロールするコンテンツがある場合にスクロールができなくなってしまうので、以下の様に設定します。
sheet.prefersScrollingExpandsWhenScrolledToEdge = false
これにより、モーダルの高さ変更の操作はTopBarの領域のみになり、モーダル内のコンテンツでスクロールを行える様になります。
モーダルのTopBarの領域にグラバーを表示します。
sheet.prefersGrabberVisible = true
上記のprefersScrollingExpandsWhenScrolledToEdgeをfalseにした場合に、スワイプできる領域がわかりやすくなります。
sheet.preferredCornerRadius = 24.0
モーダル上部の角丸も指定できます、0を指定すれば角丸をなくすことができるはずなのですが、mediumだと0を指定しても若干角丸があります。
初期設定のハーフモーダルだと親Viewが薄暗くなっており、そこをタップするとモーダルが閉じてしまいますが、ハーフモーダルを表示しつつ、親Viewも操作したい場合は以下の様にします。
sheet.largestUndimmedDetentIdentifier = .medium
ライブラリを使うことなく、簡単にハーフモーダルを実装できる様になったので、ぜひ使ってみてください!