😎

SwiftUIのNavigationViewで画面全体に背景色を適用する

2021/02/02に公開
1

SwiftUINavigationViewで画面全体に背景色を適用したいときはZStackを利用します。

struct ContentView: View {
    var body: some View {
        NavigationView {
            ZStack {
                Color.green.edgesIgnoringSafeArea(.all)
                Text("Hello, SwiftUI")
                    .font(.title)
            }
            .navigationTitle("NavigationView")
        }
    }
}

しかし、この方法では以下のようにNavigationViewのタイトルがインラインで表示された時に期待通りになりません。

struct ContentView: View {
    var body: some View {
        NavigationView {
            ZStack {
                Color.green.edgesIgnoringSafeArea(.all)
                Text("Hello, SwiftUI")
                    .font(.title)
            }
            .navigationTitle("NavigationView")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

これを回避するにはUIKitのUINavigationBarAppearanceを使ってNavigationBarの色を指定します。

let coloredNavAppearance = UINavigationBarAppearance()

struct ContentView: View {
    init() {
        coloredNavAppearance.configureWithOpaqueBackground()
        coloredNavAppearance.backgroundColor = UIColor.init(red: 41/255, green: 199/255, blue: 50/255, alpha: 1.0)
//        coloredNavAppearance.titleTextAttributes = [.foregroundColor: UIColor.black]
//        coloredNavAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
        UINavigationBar.appearance().standardAppearance = coloredNavAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredNavAppearance
    }
    var body: some View {
        NavigationView {
            ZStack {
                Color(red: 41/255, green: 199/255, blue: 50/255, opacity: 1.0).edgesIgnoringSafeArea(.all)
                Text("Hello, SwiftUI")
                    .font(.title)
            }
            .navigationTitle("NavigationView")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

上記の処理はアプリの中で一度だけ実行すれば良さそうです、iOS14以降であれば@mainのAppクラスに実装するとことで実現できそうです。

@main
struct MyApp: App {
    init() {
        let coloredNavAppearance = UINavigationBarAppearance()
        coloredNavAppearance.configureWithOpaqueBackground()
        coloredNavAppearance.backgroundColor = UIColor.init(red: 41/255, green: 199/255, blue: 50/255, alpha: 1.0)
        UINavigationBar.appearance().standardAppearance = coloredNavAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredNavAppearance
    }
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

また、backgroundColorには透過色を指定するだけでも良さそうです。例えばUINavigationControllerviewDidLoadを拡張してbackgroundColorにclearを指定すると背景色を全体に表示させることができました。

extension UINavigationController {
    override open func viewDidLoad() {
        super.viewDidLoad()
        let appearance = UINavigationBarAppearance()
        appearance.configureWithTransparentBackground()
        appearance.backgroundColor = UIColor.clear
        navigationBar.standardAppearance = appearance
    }
}

記事が参考にったらいいねしていただけると嬉しいです。

Discussion