89 votes

SwiftUI met à jour la couleur du titre de la barre de navigation

Comment changer la couleur du titre de la barre de navigation dans SwiftUI

NavigationView {
            List{
                ForEach(0..<15) { item in
                    HStack {
                        Text("Apple")
                            .font(.headline)
                            .fontWeight(.medium)
                            .color(.orange)
                            .lineLimit(1)
                            .multilineTextAlignment(.center)
                            .padding(.leading)
                            .frame(width: 125, height: nil)

                        Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
                            .font(.subheadline)
                            .fontWeight(.regular)
                            .multilineTextAlignment(.leading)
                            .lineLimit(nil)

                    }
                }
            }
            .navigationBarTitle(Text("TEST")).navigationBarHidden(false).foregroundColor(.orange)
            }

J'ai essayé avec .foregroundColor(.orange) mais cela ne fonctionne pas

a également essayé .navigationBarTitle(Text("TEST").color(.orange))

Comment faire ?

3 votes

Hm... il semble que swiftUI ignore tout modificateur défini pour le titre de la barre de navigation... Et il est également étrange que nous ne pouvons pas mettre n'importe quelle vue dans la barre de navigation :-(

153voto

arsenius Points 536

Il est no nécessaire d'utiliser .appearance() pour le faire de manière globale.

Bien que SwiftUI n'expose pas directement le style de navigation, vous pouvez contourner ce problème en utilisant la fonction UIViewControllerRepresentable . Puisque SwiftUI utilise un UINavigationController derrière les coulisses, le contrôleur de vue aura toujours une adresse valide .navigationController propriété.

struct NavigationConfigurator: UIViewControllerRepresentable {
    var configure: (UINavigationController) -> Void = { _ in }

    func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController {
        UIViewController()
    }
    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) {
        if let nc = uiViewController.navigationController {
            self.configure(nc)
        }
    }

}

Et pour l'utiliser

struct ContentView: View {
    var body: some View {
        NavigationView {
            ScrollView {
                Text("Don't use .appearance()!")
            }
            .navigationBarTitle("Try it!", displayMode: .inline)
            .background(NavigationConfigurator { nc in
                nc.navigationBar.barTintColor = .blue
                nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
            })
        }
    .navigationViewStyle(StackNavigationViewStyle())
    }
}

Modified navigation bar

41voto

Anjali Kevadiya Points 22

Dans SwiftUI, vous ne pouvez pas modifier directement la couleur du titre de navigation. Vous devez modifier l'apparence de l'UINavigation dans le module init() comme ça,

struct YourView: View {

    init() {
        //Use this if NavigationBarTitle is with Large Font
        UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor.red]

        //Use this if NavigationBarTitle is with displayMode = .inline
        UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.red]
    }

    var body: some View {

        NavigationView {
            List{
                ForEach(0..<15) { item in
                    HStack {
                        Text("Apple")
                            .font(.headline)
                            .fontWeight(.medium)
                            .color(.orange)
                            .lineLimit(1)
                            .multilineTextAlignment(.center)
                            .padding(.leading)
                            .frame(width: 125, height: nil)

                        Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
                            .font(.subheadline)
                            .fontWeight(.regular)
                            .multilineTextAlignment(.leading)
                            .lineLimit(nil)
                    }
                }
            }
            .navigationBarTitle(Text("TEST")).navigationBarHidden(false)
            //.navigationBarTitle (Text("TEST"), displayMode: .inline)
        }
    }
}

J'espère que cela fonctionnera. Merci !

1 votes

Savez-vous comment on peut faire cela en utilisant SwiftUI sur WatchOS ?

1 votes

Je reçois une erreur : Use of unresolved identifier 'UINavigationBar'

0 votes

NavigationView n'est pas disponible dans watchOS.

32voto

Thahir Points 663

Dans iOS 14, SwiftUI dispose d'un moyen de personnaliser une barre de navigation avec la nouvelle fonction toolbar modificateur.

Nous devons mettre ToolbarItem de type de placement .principal à un nouveau toolbar modificateur. Vous pouvez même définir une image et bien plus encore.

NavigationView {
    Text("My View!")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .principal) {
                HStack {
                    Image(systemName: "sun.min.fill")
                    Text("Title")
                        .font(.headline)
                        .foregroundColor(.orange)
                }
            }
        }
}

11 votes

Mais vous ne seriez pas en mesure de définir la couleur de fond de la barre d'outils, n'est-ce pas ?

0 votes

Cela ne fonctionne que pour displayMode .inline comme vous l'avez ici, mais pas pour .large

1 votes

Cela ne répond pas à la question.

25voto

Phillip Points 181

J'ai cherché ce problème et j'ai trouvé un excellent article à ce sujet. Vous pourriez envelopper les paramètres du style de la barre de navigation comme un modificateur de vue.

Vérifiez ceci Lien .

Notes : Je crois que vous devez mettre à jour certains codes dans cet exemple, ajoutez titleColor paramètre.

struct NavigationBarModifier: ViewModifier {

    var backgroundColor: UIColor?
    var titleColor: UIColor?

    init(backgroundColor: UIColor?, titleColor: UIColor?) {
        self.backgroundColor = backgroundColor
        let coloredAppearance = UINavigationBarAppearance()
        coloredAppearance.configureWithTransparentBackground()
        coloredAppearance.backgroundColor = backgroundColor
        coloredAppearance.titleTextAttributes = [.foregroundColor: titleColor ?? .white]
        coloredAppearance.largeTitleTextAttributes = [.foregroundColor: titleColor ?? .white]

        UINavigationBar.appearance().standardAppearance = coloredAppearance
        UINavigationBar.appearance().compactAppearance = coloredAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
    }

    func body(content: Content) -> some View {
        ZStack{
            content
            VStack {
                GeometryReader { geometry in
                    Color(self.backgroundColor ?? .clear)
                        .frame(height: geometry.safeAreaInsets.top)
                        .edgesIgnoringSafeArea(.top)
                    Spacer()
                }
            }
        }
    }
}

extension View {

    func navigationBarColor(backgroundColor: UIColor?, titleColor: UIColor?) -> some View {
        self.modifier(NavigationBarModifier(backgroundColor: backgroundColor, titleColor: titleColor))
    }

}

Après cela, appliquez comme ceci :

.navigationBarColor(backgroundColor: .clear, titleColor: .white)

J'espère que ça va marcher.

14voto

En me basant sur la réponse d'Arsenius, j'ai trouvé qu'une manière élégante d'obtenir un fonctionnement cohérent était de sous-classer UIViewController et faire la configuration dans viewDidLayoutSubviews() .

Uso:

VStack {
    Text("Hello world")
        .configureNavigationBar {
            $0.navigationBar.setBackgroundImage(UIImage(), for: .default)
            $0.navigationBar.shadowImage = UIImage()
        }
}

Mise en œuvre :

extension View {
    func configureNavigationBar(configure: @escaping (UINavigationController) -> Void) -> some View {
        modifier(NavigationConfigurationViewModifier(configure: configure))
    }
}

struct NavigationConfigurationViewModifier: ViewModifier {
    let configure: (UINavigationController) -> Void

    func body(content: Content) -> some View {
        content.background(NavigationConfigurator(configure: configure))
    }
}

struct NavigationConfigurator: UIViewControllerRepresentable {
    let configure: (UINavigationController) -> Void

    func makeUIViewController(
        context: UIViewControllerRepresentableContext<NavigationConfigurator>
    ) -> NavigationConfigurationViewController {
        NavigationConfigurationViewController(configure: configure)
    }

    func updateUIViewController(
        _ uiViewController: NavigationConfigurationViewController,
        context: UIViewControllerRepresentableContext<NavigationConfigurator>
    ) { }
}

final class NavigationConfigurationViewController: UIViewController {
    let configure: (UINavigationController) -> Void

    init(configure: @escaping (UINavigationController) -> Void) {
        self.configure = configure
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        if let navigationController = navigationController {
            configure(navigationController)
        }
    }
}

0 votes

Cela résout le problème lorsque le contrôleur de navigation est nul au premier chargement. Merci !

1 votes

Cela fonctionne définitivement mieux. Testé sur iOS 14

0 votes

Heureux d'avoir pu aider !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X