iOS16+からのアップデートで、SwiftUIでもハーフモーダルを実装することができるようになりました!
本記事では、SwiftUIにおけるsheetの基本機能のおさらいとともに、ハーフモーダルの実装と、その他オプションの使い方についても触れていきたいと思います。
本記事のソースコード
[ 本記事はこんな人におすすめ ]
・iOS16+から使えるSwiftUIのハーフモーダルを知りたい
・iOS16+の新機能を知りたい
・SwiftUIでアプリ開発をしている
iOS16+から、SwiftUIのsheetでハーフモーダルを実装することができるようになりました。
ハーフ(半分)表示のほか、「高さ」や「画面割合」の指定によってシートの高さをカスタマイズすることもできます。
SwiftUIにおけるsheetの基本機能をおさらいしておきます。
基本実装コードは以下です。
// SwiftUIにおけるsheetの基本的な記述
struct BasicSheetView: View {
@State private var isShowSheet = false
var body: some View {
Button("シートを表示") {
isShowSheet.toggle()
}
.sheet(isPresented: $isShowSheet,
onDismiss: didDismiss) {
SheetView(show: $isShowSheet)
}
}
func didDismiss() {
// シートを破棄した時の処理...
}
}
引数「onDismiss:」にはシート破棄時の処理を設定することができます。
iOS16+で登場したメソッドです。シートに対して高さを指定できます。
sheet内で定義しているビューに対して設定します。
// ハーフシートモーダルの実装
struct HalfsheetView: View {
@State private var isShowSheet = false
var body: some View {
Button("シートを表示") {
isShowSheet.toggle()
}
.sheet(isPresented: $isShowSheet) {
HalfSheetDetails(show: $isShowSheet)
.presentationDetents([.medium]) // ⬅︎
}
}
}
[.medium, .large]と指定すれば、全画面とハーフ画面の両方を使用することもできます。
// ハーフ画面、全画面、両方のサポート
.presentationDetents([
.medium,
.large,
])
「height」で高さ、「fraction」で画面割合によるシート幅のカスタム指定ができます。
また、これらはデフォルトの.mediumや.largeと共存可能です。
// シートの高さをカスタム指定
.presentationDetents([
.medium,
.large,
// 高さ
.height(200),
// 画面に対する割合
.fraction(0.8)
])
presentationDetentsの第二引数「selection:」にステートプロパティを設定することで、シートの表示状態を監視することができます。
シートの表示状態によってビューを変化させたい場合に活用できます。
@State private var presentationDetent = PresentationDetent.medium
//...
.presentationDetents([.medium, .large], selection: $presentationDetent)
// シートの表示状態を監視する
struct GetSheetStateView: View {
@State private var isShowSheet = false
// シートの状態を取得するために用いるプロパティ
@State private var presentationDetent = PresentationDetent.medium
var body: some View {
Button("シートを表示") {
isShowSheet.toggle()
}
.sheet(isPresented: $isShowSheet) {
SheetStateDetails(show: $isShowSheet,
state: presentationDetent)
// 第二引数「selection:」にStateプロパティを設定
.presentationDetents([
.medium,
.large,
], selection: $presentationDetent) // ⬅︎
}
}
}
下記の実装では、取得したシートの状態をシート側のビューに渡しています。
上記のようなステートプロパティによる監視をしている場合、シートの画面破棄時の表示状態が残り、シート再表示時に状態がそのまま反映されます。(全画面状態でシートを閉じれば、再表示時も全画面になる)
シートの初期表示を固定したい場合は、sheetの引数「onDismiss:」に初期化メソッドを設定してください。
// 引数「onDismiss:」に状態初期化メソッドを設定
.sheet(isPresented: $isShowSheet,
onDismiss: didDismiss) {
// ...
// シートの初期表示を固定化するためのメソッド
func didDismiss() {
presentationDetent = .medium
}
独自にカスタムしたシート幅をアプリ内共通で使用するような場合は、extensionで管理しておくと便利です。
// シート幅のカスタム指定をextensionで管理
extension PresentationDetent {
static let small = Self.height(100)
static let big = Self.fraction(0.75)
}
// ...
// 管理したカスタム指定が使える
.presentationDetents([
.small,
.medium,
.big,
.large
])
iPhone横向きの状態など、縦方向にコンパクトな環境では、シートがフルスクリーンカバーに自動調整され、スワイプによる破棄ができないので注意してください。
iOS16.4+のpresentationCompactAdaptationメソッドで、状態ごとのシート表示を明示的に指定できるようですが、スワイプ破棄はできるものの期待した表示にはなりませんでした。
presentationCompactAdaptation(_:) | Apple Developer Documentation
横表示をサポートしている場合は、シートを破棄できるシステム(ボタンアクションなど)を用意しておいた方が良いですね。
以上、iOS16+におけるSwiftUIのsheet、ハーフモーダルの実装について書かせていただきました。
要点をまとめておきます。
・presentationDetentsモディファイアを使って表示を指定する
・ハーフ画面、全画面、両方のサポートが可能(.medium, .large)
・シートの高さはカスタムで指定ができる(.height, .fraction)
本記事が参考になれば幸いです。
\ SHARE /
アプリ開発が学べる勉強会を開催中!
CodeCandyではアプリ開発を学ぶための勉強会を定期開催しています。
学習する習慣を身につけたい、他の参加者と作業したい、アプリ開発の基本をマスターしたい、という方のために無料で学べる勉強会です。
グループにメンバー登録して頂くと、イベント開催時にメールで通知されます。
徹底した基礎学習からマスターするiPhoneアプリ開発集中オンライン講座開講!
本書「iPhoneアプリ開発集中講座」を執筆している現役エンジニア講師陣が直接に指導!
基礎、課題実習で実践力を鍛えて、オリジナルアプリ公開までチャレンジ!
充実した転職支援もあるので、エンジニアへ転職したい人にもおすすめです!
まずは、現役エンジニアに相談できる無料相談をご利用ください。
2022年2月よりSwift学習を始め、4月からiOSアプリ開発オンラインスクール「CodeCandy」にてアプリ開発を学ぶ。 2023年10月に個人開発アプリ「unico」をリリース。現在はアプリの機能アップデートをしながら、スクール運営の技術ブログの執筆や、出版書籍の入稿チェック・デバッグにも携わる。