SwiftUIでナビゲーションバー(NavigationView)の色を変更する

f:id:bamboohero:20210520091836p:plain 現状のSwiftUIではナビゲーションバー(NavigationView)の色を変更するModifierが提供されていません。

しかし、ナビゲーションバーの色を変更したいモチベーションは多々あると思います。

本記事では、ViewModifierを使ってナビゲーションバーのスタイルを変更する方法についてご紹介します。



ナビゲーションバーのスタイルを変更するViewModifierを実装する

ViewModifierというのは、複数のModifierを一つにまとめてスタイリングの処理を共通化するための仕組みです。

https://developer.apple.com/documentation/swiftui/reducing-view-modifier-maintenance

以下のようにカスタムModifierを実装します。

struct NavigationBarModifier: ViewModifier {
    let backgroundColor: UIColor

    init(backgroundColor: UIColor) {
        self.backgroundColor = backgroundColor

        // [1]
        let coloredAppearance = UINavigationBarAppearance()
        coloredAppearance.configureWithTransparentBackground()
        coloredAppearance.backgroundColor = backgroundColor
        coloredAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        coloredAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]

        // [2]
        UINavigationBar.appearance().standardAppearance = coloredAppearance
        UINavigationBar.appearance().compactAppearance = coloredAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
        UINavigationBar.appearance().tintColor = .white
    }

    func body(content: Content) -> some View {
        // [3]
        content
//        ZStack{
//            content
//            VStack {
//                GeometryReader { geometry in
//                    Color(backgroundColor)
//                        .frame(height: geometry.safeAreaInsets.top)
//                        .edgesIgnoringSafeArea(.top)
//                    Spacer()
//                }
//            }
//        }
    }
}

extension View {
    func navigationBarColor(_ backgroundColor: UIColor) -> some View {
        modifier(NavigationBarModifier(backgroundColor: backgroundColor))
    }
}

ナビゲーションバーの色を変更したいときは以下のように実装します。

NavigationView {
    Text("Hello")
        .navigationBarTitleDisplayMode(.inline)
        .navigationBarColor(.blue)
}


f:id:bamboohero:20210520011853p:plain:w300

コードの解説

[1]
SwiftUIではナビゲーションバーの色を変更する手段が用意されていないので、UIKitの仕組みを使います。UINavigationBarAppearanceはiOS13で追加された、ナビゲーションバー周りの見た目を変更するためのオブジェクトです。 ここでbackgroundColorに引数で渡された色を指定しておきます。

[2]
UINavigationBar.appearance()に対して先に作成したUINavigationBarAppearanceオブジェクトを適用します。なお、UINavigationBar.appearance()に対して変更をあてると全てのナビゲーションバーに反映されてしまいます。画面によってナビゲーションバーの色が異なる場合、常に色の指定をしておく必要があります。

[3]
参考記事ではコメントアウトしている部分の実装がされているのですが、実際動かしてみたところこのコードがなくてもナビゲーションバーの色は変更されました。 いまいち必要性がわかっていないのですが、今後何か判明したら追記しようと思います。

ステータスバーの文字色を変更する

ナビゲーションバーに青や黒といった色を指定するときは、ステータスバーの文字色が白のほうが良いですね。

ステータスバーの文字色を白にするには、以下の2つのプロパティを設定する必要があります。

まず、ターゲットのGeneralタブを表示し、Deployment Info > Status Bar Styleの値をLight Contentに変更します。

f:id:bamboohero:20210520030652p:plain:w500

続いて、Infoタブを表示し、Custom iOS Target Propertiesに以下のキーバリュー値を設定します。

  • Key: View controller-based status bar appearance
  • Value: NO

f:id:bamboohero:20210520030925p:plain:w500

これでステータスバーの文字色も変わりました。

f:id:bamboohero:20210520091506p:plain:w300

参考記事