LoginSignup
3
4

【SwiftUI】NavigationStackの戻るボタンをカスタマイズする

Last updated at Posted at 2023-10-30

NavigationStackを使用して画面遷移を行う際、必ず左上に< Backというボタンが表示されます。このボタンをカスタマイズしてアプリの雰囲気に調和したデザインに変更したいと思います。

スクリーンショット 2023-10-31 0.47.38.png

NavigationStackで画面遷移を記述する

シンプルにFirstViewSecondViewを作成するとこんな感じです。

ソースコード

FirstView.swift
struct FirstView: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("FirstView")
                Spacer()
                    .frame(height: 50)
                NavigationLink(destination: SecondView(), label: {
                    Text("SecondView")
                })
            }
        }
    }
}
SecondView.swift
struct SecondView: View {
    var body: some View {
        Text("SecondView")
    }
}

完成イメージ

FirstView SecondView
スクリーンショット 2023-10-31 1.00.45.png スクリーンショット 2023-10-31 1.01.06.png

FirstViewSecondViewをタップすると画面遷移するというシンプルな構造にしています。

戻るボタンをカスタマイズする

初期状態だと青くて普通のボタンなので、SF Symbolsからとってきた戻る矢印に差し替えましょう。
カスタマイズは戻るボタンが表示されるSecondViewに記述します。

ソースコード

SecondView.swift
struct SecondView: View {
    @Environment(\.dismiss) var dismiss

    var body: some View {
        Text("SecondView")
            .navigationBarBackButtonHidden(true)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(
                        action: {
                            dismiss()
                        }, label: {
                            Image(systemName: "arrow.uturn.backward")
                        }
                    ).tint(.black)
                }
            }
    }
}

コードについて説明していきます。

.navigationBarBackButtonHidden(Bool)

.navigationBarBackButtonHidden(true)は元のボタンを消す役割があります。

これは戻るボタンが表示がされなくなるだけでなく、画面端をスワイプすることで戻る機能も失われるので、UXが低下する恐れがあります。

スワイプ機能を追加で実装する方法を以下の記事にまとめたので興味がある方はぜひご覧ください。

.toolBar

このModifierの中でToolBarItemを記述することで、上部の戻るボタンをカスタマイズすることができます。
ToolBarItemの引数のplacement.navigationBarLeadingとすることで、戻るボタンの位置にオリジナルのボタンを配置することができます。

dismiss()

Environment(\.dismiss) var dismissと記述していますが、これはcallAsFunctionというもので、dismissという画面を破棄する機能をインスタンスとして呼び出すことができます。

完成イメージ

スクリーンショット 2023-10-31 1.38.32.png

こんな感じで黒い矢印に変更することができました。

Extensionを使って記述を簡略化する

遷移先がサンプルのように簡単ならこのままでいいですが、実際はそんなこともないと思うので、1行のModifierで記述できるようにします。

ソースコード

View+NavigationBackButton.swift
struct NavigationBackButton: ViewModifier {
    @Environment(\.dismiss) var dismiss

    func body(content: Content) -> some View {
        content
            .navigationBarBackButtonHidden(true)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(
                        action: {
                            dismiss()
                        }, label: {
                            Image(systemName: "arrow.uturn.backward")
                        }
                    ).tint(.black)
                }
            }
    }
}

extension View {
    
    func navigationBackButton() -> some View {
        self.modifier(NavigationBackButton())
    }
}

このようにしてViewextensionとしてModifierを定義することで.navigationBackButton()SecondViewに記述するだけでカスタマイズが可能になります。

終わりに

Extensionを活用することで非常にシンプルに実装することができました。今回はSF Symbolsを使いましたが、オリジナルの画像などを配置することも可能なので、アプリのデザインに合わせて変えてみるといいと思います。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4