iOS16+からのアップデートで、SwiftUIでもハーフモーダルを実装することができるようになりました!

本記事では、SwiftUIにおけるsheetの基本機能のおさらいとともに、ハーフモーダルの実装と、その他オプションの使い方についても触れていきたいと思います。

本記事のソースコード

本記事で使用しているサンプルコードはGitHubにて公開されています。

コード内容の確認にご利用ください🍎

GitHubを見に行く>>

【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

[ 本記事はこんな人におすすめ ]

・iOS16+から使えるSwiftUIのハーフモーダルを知りたい

・iOS16+の新機能を知りたい

・SwiftUIでアプリ開発をしている

概要

iOS16+から、SwiftUIのsheetでハーフモーダルを実装することができるようになりました。

ハーフ(半分)表示のほか、「高さ」や「画面割合」の指定によってシートの高さをカスタマイズすることもできます。

【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

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:」にはシート破棄時の処理を設定することができます。

【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

ハーフモーダルの実装方法

presentationDetents

iOS16+で登場したメソッドです。シートに対して高さを指定できます。

sheet内で定義しているビューに対して設定します。

【SwiftUI】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]) // ⬅︎
        }
    }
}
				
			
【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

[.medium, .large]と指定すれば、全画面とハーフ画面の両方を使用することもできます。

				
					// ハーフ画面、全画面、両方のサポート
.presentationDetents([
    .medium,
    .large,
])
				
			
【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

高さをカスタム指定する(height, fraction)

height」で高さ、「fraction」で画面割合によるシート幅のカスタム指定ができます。

また、これらはデフォルトの.mediumや.largeと共存可能です。

				
					// シートの高さをカスタム指定
.presentationDetents([
    .medium,
    .large,
    // 高さ
    .height(200),
    // 画面に対する割合
    .fraction(0.8)
])
				
			
【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

シートの状態を取得する

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) // ⬅︎
        }
    }
}
				
			

下記の実装では、取得したシートの状態をシート側のビューに渡しています。

【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

シート監視時の表示状態について

上記のようなステートプロパティによる監視をしている場合、シートの画面破棄時の表示状態が残り、シート再表示時に状態がそのまま反映されます。(全画面状態でシートを閉じれば、再表示時も全画面になる)

シートの初期表示を固定したい場合は、sheetの引数「onDismiss:」に初期化メソッドを設定してください。

				
					// 引数「onDismiss:」に状態初期化メソッドを設定
.sheet(isPresented: $isShowSheet,
       onDismiss: didDismiss) {
       
       // ...

// シートの初期表示を固定化するためのメソッド
func didDismiss() {
        presentationDetent = .medium
}
				
			

シートの高さをextensionで管理する

独自にカスタムしたシート幅をアプリ内共通で使用するような場合は、extensionで管理しておくと便利です。

				
					// シート幅のカスタム指定をextensionで管理
extension PresentationDetent {
    static let small = Self.height(100)
    static let big = Self.fraction(0.75)
}
// ...

// 管理したカスタム指定が使える
.presentationDetents([
    .small,
    .medium,
    .big,
    .large
])
				
			
【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

sheetの注意点

横スクリーン時のsheetの挙動について

iPhone横向きの状態など、縦方向にコンパクトな環境では、シートがフルスクリーンカバーに自動調整され、スワイプによる破棄ができないので注意してください。

【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて
「戻る」ボタンがないためシートを破棄できない

iOS16.4+のpresentationCompactAdaptationメソッドで、状態ごとのシート表示を明示的に指定できるようですが、スワイプ破棄はできるものの期待した表示にはなりませんでした。

presentationCompactAdaptation(_:) | Apple Developer Documentation 

【SwiftUI】iOS16+のsheet|ハーフモーダルの使い方とオプションについて

横表示をサポートしている場合は、シートを破棄できるシステム(ボタンアクションなど)を用意しておいた方が良いですね。

まとめ

以上、iOS16+におけるSwiftUIのsheet、ハーフモーダルの実装について書かせていただきました。

要点をまとめておきます。

presentationDetentsモディファイアを使って表示を指定する

ハーフ画面、全画面、両方のサポートが可能(.medium, .large)

・シートの高さはカスタムで指定ができる(.height, .fraction)

本記事が参考になれば幸いです。

\  SHARE  /

Twitter
Facebook
Email

✏️ アプリ開発が学べる勉強会を開催中! 

CodeCandyではアプリ開発を学ぶための勉強会を定期開催しています。
学習する習慣を身につけたい、他の参加者と作業したい、アプリ開発の基本をマスターしたい、という方のために無料で学べる勉強会です。
グループにメンバー登録して頂くと、イベント開催時にメールで通知されます。

▶️グループのメンバーとして参加する

徹底した基礎学習からマスターするiPhoneアプリ開発集中オンライン講座開講!

本書「iPhoneアプリ開発集中講座」を執筆している現役エンジニア講師陣が直接に指導!
基礎、課題実習で実践力を鍛えて、オリジナルアプリ公開までチャレンジ!
充実した転職支援もあるので、エンジニアへ転職したい人にもおすすめです!

まずは、現役エンジニアに相談できる無料相談をご利用ください。

\ Official /

By 中川 賢亮

2022年2月よりSwift学習を始め、4月からiOSアプリ開発オンラインスクール「CodeCandy」にてアプリ開発を学ぶ。 2023年10月に個人開発アプリ「unico」をリリース。現在はアプリの機能アップデートをしながら、スクール運営の技術ブログの執筆や、出版書籍の入稿チェック・デバッグにも携わる。