【SwiftUI】NavigationViewの使い方!戻るボタンの自作方法
この記事からわかること
- Swift UIのNavigationViewとは?
- 書式や使い方、メリット
- iOSアプリ開発での画面遷移の実装方法
- タイトルを付与するには?
- 「Back」ボタンを非表示にする
- 戻るボタンを自作する方法
- ナビゲーションバーの文字色を変更する方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
Swift UIで簡単に画面遷移を実装できる「NavigationView」の使い方についてまとめていきたいと思います。
NavigationViewとは?
NavigationView
はSwift UIのView構造体の1つで、階層的なページに対して簡単に画面遷移を実装することができます。
またNavigationView
で囲っている中の要素のデザインも自動で変更してくれます。ListやPickerなどをよりiPhoneらしく、使い勝手の良い仕様に変えてくれるのもメリットの1つです。
しかしiOS13.0〜16.0はDeprecated(非推奨)になっていました。使用する際はご注意ください。
iOS16.0以降はNavigationStack
またはNavigationSplitView
の置き換えが推奨されています。
基本的な使い方
使い方はNavigationView{}
で要素を囲むだけです。中に設定する要素をListで囲うことで見た目もiPhoneの設定画面のような仕様に変更してくれます。
struct ContentView: View {
var body: some View {
NavigationView {
List {
Text("要素1")
Text("要素2")
Text("要素3")
}
}
}
}
画面遷移させる
NavigationView
の醍醐味である画面遷移を実装するにはNavigationView{}
で囲んだ中でNavigationLink
を使用して遷移先を指定します。NavigationLink
はナビゲーションリンクを生成し、実際の画面遷移を実装するView構造体です。
おすすめ記事:【Swift UI】NavigationLinkの使い方!navigationDestinationとの組み合わせ
実装のポイント
- NavigationView構造体の中に追加
- NavigationLink構造体
- 書式は複数ある
- 引数destinationにリンク先にするビューを渡す
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink {
// 遷移先のビューを指定
ChildView()
} label: {
// リンクボタンのテキストを指定
Label("ChildViewへ", systemImage: "arrowshape.turn.up.right.fill")
}
}
}
}
NavigationLink
のイニシャライザは色々あります。他のイニシャライザでは引数destination
に遷移先を指定します。
別のイニシャライザ
init(
destination: () -> Destination,
label: () -> Label
)
画面遷移させるリンクをクリックすると実際に画面が切り替わります。前の画面に戻るには左上に自動で実装される「Back」ボタンを押します。この文字は後述しているタイトルを付与することで自動で変更されます。
タイトルを付与する
NavigationView
内に指定している要素にタイトルを付与するには、navigationTitle
モディファイアを使用します。このモディファイアはNavigationViewではなく中の要素に対して付与するしないと機能しないので注意してください。
実装のポイント
- NavigationView構造体の中の要素に指定
- navigationTitleモディファイア
- 遷移後の戻るボタンはタイトル名に変わる
struct ContentView: View {
var body: some View {
NavigationView {
List {
Text("要素1")
Text("要素2")
NavigationLink("リンク1") {
ChildView()
}
} .navigationTitle("タイトル")
}
}
}
またタイトルを付与したことで遷移後の画面の「Back」ボタンも「タイトル」ボタンへと変更されます。
ナビゲーションバー(タイトル)を非表示にする
「Back」ボタンの文字を変えるためにタイトルは指定したいけど表示させたくない場合はタイトルのあるナビゲーションバーをnavigationBarHidden
モディファイアを使って非表示にすることで解決できます。
struct ContentView: View {
var body: some View {
NavigationView {
List {
Text("要素1")
Text("要素2")
NavigationLink("リンク1") {
ChildView()
}
} .navigationTitle("タイトル")
.navigationBarHidden(true)
}
}
}
toolbar(_:for:)で非表示にする
navigationBarHidden
モディファイアはiOS16以降非推奨になったのでナビゲーションバーを非表示するにはtoolbar(_:for:)
モディファイアを使用します。
.toolbar(.hidden, for: .navigationBar)
「Back」ボタンを非表示にする
ナビゲーションバーにデフォルトで表示される「Back」ボタンを表示させたくない場合は子View側にnavigationBarBackButtonHidden
モディファイアを使えば非表示にすることができます。
struct ChildView: View {
var body: some View {
Text("ChildView")
}.navigationBarBackButtonHidden(true)
}
上部にツールバーを実装する
NavigationView
にはタイトルだけでなく上部にボタンなどを配置するツールバーを実装できます。toolbar
モディファイアをnavigationTitle
と同じく中の要素に指定しToolbarItem
構造体を使用して実装します。
実装のポイント
- NavigationView構造体に指定
- toolbarモディファイア
- その中にToolbarItem構造体
- 引数placementには揃え位置を指定
struct ContentView: View {
var body: some View {
NavigationView {
List {
Text("要素1")
Text("要素2")
NavigationLink("リンク1") {
ChildView()
}
} .navigationTitle("タイトル")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
print("設定ボタンです")
}) {
Image(systemName: "gearshape.fill")
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
print("マイページです")
}){
HStack {
Image(systemName: "person.fill")
}
}
}
}
}
}
}
toolbar
モディファイアの中にはToolBarItem
構造体を指定し、その中にボタンを設置します。引数placement
には要素の揃え位置を指定します。
リンクの有効/無効を切り替える
リンクボタンは有効/無効を切り替えることもできます。無効にするにはNavigationLink
構造体にたいしてdisabled(true)
を指定します。
実装のポイント
- NavigationLink構造体に指定
- disabledモディファイアに真偽値を渡す
struct ContentView: View {
var body: some View {
NavigationView {
List {
Text("要素1")
Text("要素2")
NavigationLink("リンク1") {
ChildView()
}.disabled(true) // 無効にする
} .navigationTitle("タイトル")
}
}
}
戻るボタンを実装する
遷移後の画面から戻るためのボタンはデフォルトで用意されていますが、戻るボタンを自力で実装することも可能です。例えばButtonのアクションに戻る機能を実装してみます。こちらは遷移後側のビューに作成します。
実装のポイント
- 子供側に実装
- 環境変数dismissを使用可能にする
- アクション部分でdismiss()を実行
struct ChildView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
Button(action: {
dismiss()
}, label: {
Text("戻るボタン")
})
}
}
詳細は以下の記事を参考にしてください。
Pickerをナビゲーションリンクで開く
Picker
のアイテム選択画面をリンクで開かさせるにはPicker
をNavigationView
構造体とForm
構造体で囲みます。どうやらPicker
自体がナビゲーションの機能を使用しているらしく、ラップしないと正常に動作しないようです(どこかで見ましたがソースに辿り着けず…)。
実装のポイント
- NavigationView構造体で囲む
- さらにForm構造体で囲む
- Pickerはナビゲーションの機能を使用
- Formでラップしないと正常に動作しない
struct ContentView: View {
@State var selectedLang = 0
let lang = ["HTML", "CSS", "PHP", "Swift", "C"]
var body: some View {
NavigationView{
Form{
Picker(selection: $selectedLang, label: Text("言語")) {
ForEach(lang.indices, id:\.self) { index in
Text(lang[index])
}
}
}
}
}
}
Pickerを囲むとデザインが以下のようなiPhoneの設定画面のような見た目に自動で切り替わります。
戻るボタンの文字色を変更する
戻るボタンの文字色はデフォルトでは青色ですが、構造体のイニシャライザから変更することもできます。
init() {
UINavigationBar.appearance().tintColor = UIColor.orange
}
カラーに指定できるのはSwift UIのColor型ではないので注意してください。
struct ContentView: View {
init() {
UINavigationBar.appearance().tintColor = UIColor.orange
}
var body: some View {
NavigationView {
List {
Text("要素1")
Text("要素2")
NavigationLink("リンク1") {
ChildView()
}
} .navigationTitle("タイトル")
}
}
}
おすすめ記事:【SwiftUI】iPad表示でNavigationViewを全体表示するには? 分割したビューの対処法
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書