階層的な画面遷移を管理するNavigationStackの使い方を解説します。
NavigationStackはiOS16.0から使えるようになった仕組みです。それ以前のバージョンではNavigationViewを使用します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.7.1
【iOS】16.1
【macOS】Monterey バージョン 12.6
基本的な画面遷移
まずは、NavigationStackでの基本的な画面遷移の例を紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
struct ContentView: View { var body: some View { /// ナビゲーションの定義 NavigationStack { /// 画面遷移リンクの定義 NavigationLink { SecondView() // 遷移先View } label: { // 画面遷移のトリガーとなるViewの定義 Label("Go Second View", systemImage: "figure.walk") .font(.title) } .navigationTitle("Top View") // ナビゲーションタイトルの定義 } } } /// 遷移先のView定義 struct SecondView: View { var body: some View { Text("SecondView").font(.title) } } |
ナビゲーションするViewの指定
ナビゲーションを有効にするには、階層のトップ画面でNavigationStackを使用します。
1 2 3 4 5 6 7 |
NavigationStack { // ここに記述されたViewがナビゲーション管理配下となる。 } |
タイトルの指定
1 2 3 |
.navigationTitle("タイトル") |
ナビゲーションのタイトルを指定するModifierです。
注意点として、NavigationStackに関するModifierはNavigationStackそのものではなく、ナビゲーション配下のViewに適用します。
これは、遷移先のView側でタイトルを指定可能にする為の考慮と思われます。
タイトルの表示モード指定
次のModifierと組み合わせるとタイトル表示モードの指定が可能です。
1 2 3 |
.navigationBarTitleDisplayMode(表示モード) |
表示モード | 意味 |
---|---|
.large (デフォルト) |
大きなタイトル表示 拡張されたナビゲーションバー領域に大きなタイトルを表示します。 Viewをスクロールすると、.inline表示に変わります。 |
.inline | 標準のナビゲーションバー領域にタイトルを表示します。 |
.automatic | 前のナビゲーション項目の表示モードを継承します。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
struct ContentView: View { var body: some View { /// ナビゲーションの定義 NavigationStack { /// 20行のリスト定義 List(1..<21) { index in /// 画面遷移リンクの定義 NavigationLink("\(index)行目") { Text("\(index)番目のView") } } .navigationTitle("Top View") // ナビゲーションタイトル定義 .navigationBarTitleDisplayMode(.large) // タイトル表示モード指定 } } } |
NavigationStackをListやForm内で使用した場合は、上例のようにラベルテキストが青表示にはならず、代わりに右端にグレーの開示インジケーターが表示されます。
これは行をタップすると右から別の画面がスライドして表示される意図を示す、iOSの標準的なUIです。
画面遷移リンクの定義
画面遷移リンクはNavigationLinkを使って定義します。
1 2 3 |
NavigationLink(destination: () -> 遷移先View, label: () -> リンクラベル) |
Swift5.3から使えるようになったMultiple trailing closuresを使って、次のように記述できます。
1 2 3 4 5 6 7 8 9 10 11 |
NavigationLink { /// 遷移先Viewを定義 } label: { /// 遷移先を説明するラベルViewを定義 } |
最初の引数(destination)では、遷移先Viewを定義します。
次の引数(label)では、画面遷移のトリガーとなるView(ラベル)を指定します。
Textだけでなく、Imageあるいはそれらの組み合わせでの指定も可能です。
尚、ラベルが文字列のみで構成される場合は、次のイニシャライザが便利です。
1 2 3 |
NavigationLink("ラベルテキスト", destination: () -> 遷移先View) |
trailing closureを使って、次のような記述が可能です。
1 2 3 4 5 6 7 |
NavigationLink("ラベルテキスト") { /// 遷移先Viewを定義 } |
条件指定による画面遷移
次のModifierを使うと条件指定による画面遷移が実現できます。
1 2 3 |
.navigationDestination(isPresented: $条件フラグ, destination: () -> 遷移先View) |
trailing closureを使って、次のようにも記述できます。
1 2 3 4 5 6 7 |
.navigationDestination(isPresented: $条件フラグ) { /// 遷移先Viewを定義 } |
使用例
正しい合言葉を入力すると画面遷移するサンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
struct ContentView: View { @State private var password = "" // 入力された合言葉 @State private var showingSecondView = false // 画面遷移フラグ var body: some View { /// ナビゲーションの定義 NavigationStack { VStack { Text("合言葉を入力") /// テキスト入力フィールド TextField("", text: $password) .textFieldStyle(RoundedBorderTextFieldStyle()) // 枠ありスタイル .padding(.horizontal) // 左右に余白 /// 改行がタップされた時の処理定義 .onSubmit { /// 入力された合言葉が"SwiftUI"だったら画面遷移フラグをtrueにする if self.password == "SwiftUI" { self.showingSecondView = true } } } .navigationTitle("Top View") // ナビゲーションタイトルの定義 /// 画面遷移フラグがtrueになった時の遷移先を指定 .navigationDestination(isPresented: $showingSecondView) { SecondView() } } } } /// 遷移先のView定義 struct SecondView: View { var body: some View { Text("SecondView").font(.title) } } |