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

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

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

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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
struct ContentView: View {
var body: some View {
NavigationStack {
List {
Text("りんご")
Text("みかん")
Text("スイカ")
}
.navigationTitle("フルーツ")
}
}
}
struct ContentView: View { var body: some View { NavigationStack { List { Text("りんご") Text("みかん") Text("スイカ") } .navigationTitle("フルーツ") } } }
struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                Text("りんご")
                Text("みかん")
                Text("スイカ")
            }
            .navigationTitle("フルーツ")
        }
    }
}

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

NavigationStackの見た目を変更する

NavigationViewのスタイルを変更する

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
struct ContentView: View {
var body: some View {
NavigationStack {
List {
Text("りんご")
Text("みかん")
Text("スイカ")
}
.navigationTitle("フルーツ")
.navigationBarTitleDisplayMode(.inline)
}
}
}
struct ContentView: View { var body: some View { NavigationStack { List { Text("りんご") Text("みかん") Text("スイカ") } .navigationTitle("フルーツ") .navigationBarTitleDisplayMode(.inline) } } }
struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                Text("りんご")
                Text("みかん")
                Text("スイカ")
            }
            .navigationTitle("フルーツ")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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)
}
}
}
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) } } }
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行で変更する

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.navigationBarTitle("ここにタイトル", displayMode: .inline)
.navigationBarTitle("ここにタイトル", displayMode: .inline)
.navigationBarTitle("ここにタイトル", displayMode: .inline)

 

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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("削除")
}
}
}
}
}
}
}
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("削除") } } } } } } }
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のみを使った遷移

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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")
}
}
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") } }
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を使った遷移

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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)
}
}
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) } }
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)
    }
}

評価