SwiftUIの基本を身につけたい方はこちら

【SwiftUI】ナビゲーションバー(NavigationStack)の使い方について解説~基本的な使い方からナビゲーションバーの色やスタイルまで~

iOS16、Xcode14からNavigationViewが非推奨になりました。ナビゲーションバーを作るとき、これからはNavigationViewではなく、NavigationStackを使いましょう。

ということで、この記事ではNavigationStackについて徹底解説していきたいと思います。

ナビゲーションバーの基本的な実装方法

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                Text("りんご")
                Text("みかん")
                Text("スイカ")
            }
            .navigationTitle("フルーツ")
        }
    }
}

iOS15以前の実装方法との違いは、NavigationViewというところが、NavigationStackになっているだけです。

NavigationStackの見た目を変更する

NavigationViewのスタイルを変更する

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                Text("りんご")
                Text("みかん")
                Text("スイカ")
            }
            .navigationTitle("フルーツ")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

.inline.largeの二つのスタイルがあります。指定しなければ.largeになります。

ナビゲーションバーの色を変更する

struct ContentView: View {
    init() {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = UIColor.blue
        appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
        UINavigationBar.appearance().standardAppearance = appearance
        UINavigationBar.appearance().scrollEdgeAppearance = appearance
    }
    
    var body: some View {
        NavigationStack {
            List {
                Text("りんご")
                Text("みかん")
                Text("スイカ")
            }
            .navigationTitle("フルーツ")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

SwiftUIでは変えられないので、UINavigationBarで変更します。

ナビゲーションバーのタイトルの色を変更する

こちらも、SwiftUIでは変えられず、ちょっと無理矢理変える感じでした。

参考 SwiftUIでNavigationBarのBackgroundColorなどを変更する方法Qiita

ナビゲーションバーに画像を配置する

参考 SwiftUIでナビゲーションバーの中央にロゴ画像を配置する方法Qiita

タイトルとスタイルを1行で変更する

.navigationBarTitle("ここにタイトル", displayMode: .inline)

 

ナビゲーションバーにボタンを配置する

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                Text("りんご")
                Text("みかん")
                Text("スイカ")
            }
            .navigationTitle("フルーツ")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(action: {
                        print("左のボタンが押されたよ")
                    }) {
                        Image(systemName: "ellipsis.circle")
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(action: {
                        print("右のボタンが押されたよ")
                    }){
                        HStack {
                            Image(systemName: "trash")
                            Text("削除")
                        }
                    }
                }
            }
        }
    }
}

.navigationBarLeadingが左で、.navigationBarTrailingが右です。

ナビゲーションバーを使った画面遷移

NavigationLinkのみを使った遷移

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("AViewへ") {
                    AView()
                }
                
                NavigationLink("BViewへ") {
                    BView()
                }
            }
            .navigationTitle("画面遷移")
        }
    }
}

struct AView: View {
    var body: some View {
        Text("AView")
    }
}

struct BView: View {
    var body: some View {
        Text("BView")
    }
}

NavigationLink("AViewへ")でセルの文字を指定し、その中に次のViewを書くだけです。

pathを使った遷移

struct ContentView: View {
    @State private var path: [Color] = []
    
    var body: some View {
        NavigationStack(path: $path) {
            List {
                NavigationLink("Purple", value: Color.purple)
                NavigationLink("Pink", value: Color.pink)
                NavigationLink("Orange", value: Color.orange)
            }
            .navigationDestination(for: Color.self) { color in
                ColorDetail(color: color)
            }
        }
    }
}

struct ColorDetail: View {
    let color: Color
    var body: some View {
        color
            .edgesIgnoringSafeArea(.all)
    }
}

評価