簡體   English   中英

SwiftUI 更新導航欄標題顏色

[英]SwiftUI update navigation bar title color

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)
            }

我試過.foregroundColor(.orange)但它不起作用

也試過.navigationBarTitle(Text("TEST").color(.orange))

有什么幫助嗎?

沒有必要使用.appearance()來全局執行此操作。

盡管 SwiftUI 不直接公開導航樣式,但您可以使用UIViewControllerRepresentable解決這個問題。 由於 SwiftUI 在后台使用常規的UINavigationController ,因此視圖控制器仍然具有有效的.navigationController屬性。

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)
        }
    }

}

並使用它

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())
    }
}

修改后的導航欄

在 SwiftUI 中,您不能直接更改 navigationTitleColor。 您必須像這樣在init()中更改 UINavigation 的外觀,

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)
        }
    }
}

我希望它會奏效。 謝謝!!

我已經搜索了這個問題並找到了一篇很棒的文章,您可以將導航欄樣式的設置包裝為視圖修飾符。

檢查此鏈接

注意:我相信你需要在這個例子中更新一些代碼,添加titleColor參數。

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))
    }

}

之后,像這樣申請:

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

我希望它會奏效。

在 iOS 14 中,SwiftUI 可以使用新的toolbar修飾符自定義導航欄。

我們需要將放置類型ToolbarItem.principal設置為新的toolbar修飾符。 您甚至可以設置圖像等等。

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

基於 Arsenius 的回答,我發現讓它持續工作的一種優雅方法是UIViewController並在viewDidLayoutSubviews()中進行配置。

用法:

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

執行:

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)
        }
    }
}

我采取了稍微不同的方法; 只想更改標題文本顏色,而沒有其他關於NavigationBar的內容。 以上面和這個為靈感,我找到了:

import SwiftUI

extension View {
    /// Sets the text color for a navigation bar title.
    /// - Parameter color: Color the title should be
    ///
    /// Supports both regular and large titles.
    @available(iOS 14, *)
    func navigationBarTitleTextColor(_ color: Color) -> some View {
        let uiColor = UIColor(color)
    
        // Set appearance for both normal and large sizes.
        UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: uiColor ]
        UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: uiColor ]
    
        return self
    }
}

這需要 iOS 14,因為UIColor.init(_ color: Color)需要 iOS 14。

可以這樣利用:

struct ExampleView: View {
    var body: some View {
        NavigationView {
            Text("Hello, World!")
                .navigationBarTitle("Example")
                .navigationBarTitleTextColor(Color.red)
        }
    }
}

這反過來產生:

紅色導航標題

我開發了一個自定義 SwiftUI 導航的小示例,可以提供完整的可視化自定義和程序化導航。 它可以用作 NavigationView 的替代品。

這是處理 currentView 和導航堆棧的 NavigationStack 類:

final class NavigationStack: ObservableObject  {
    @Published var viewStack: [NavigationItem] = []
    @Published var currentView: NavigationItem

    init(_ currentView: NavigationItem ){
        self.currentView = currentView
    }

    func unwind(){
        if viewStack.count == 0{
            return
        }

        let last = viewStack.count - 1
        currentView = viewStack[last]
        viewStack.remove(at: last)
    }

    func advance(_ view:NavigationItem){
        viewStack.append( currentView)
        currentView = view
    }

    func home( ){
        currentView = NavigationItem( view: AnyView(HomeView()))
        viewStack.removeAll()
    }
}

你可以看看這里:完整的例子和解釋:

PS:我不知道為什么這個被刪除了。 我認為它回答了這個問題,因為它是 NavigationView 的完美功能替代品。

在 SwiftUI 中使用以下代碼自定義顏色

這是主體背景顏色:-

struct ContentView: View {

var body: some View {

 Color.red
.edgesIgnoringSafeArea(.all)

 }

}

在此處輸入圖像描述

對於導航欄:-

struct ContentView: View {

@State var msg = "Hello SwiftUI😊"

init() {

    UINavigationBar.appearance().backgroundColor = .systemPink

     UINavigationBar.appearance().largeTitleTextAttributes = [
        .foregroundColor: UIColor.white,
               .font : UIFont(name:"Helvetica Neue", size: 40)!]

}

var body: some View {

    NavigationView {

    Text(msg)

        .navigationBarTitle(Text("NAVIGATION BAR"))

    }

    }

  }

在此處輸入圖像描述

對於其他 UI 元素顏色自定義

struct ContentView: View {

@State var msg = "Hello SwiftUI😊"

var body: some View {

        Text(msg).padding()
            .foregroundColor(.white)
            .background(Color.pink)

    }
 }

在此處輸入圖像描述

init() {
    // for navigation bar title color
    UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.red]
   // For navigation bar background color 
    UINavigationBar.appearance().backgroundColor = .green
}

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)
}

如果您的內容為

struct MyContent : View {
...
}

然后你可以把它放在一個帶有紅色背景的導航視圖中:

NavigationView {
    ZStack(alignment: .top) {
        Rectangle()
            .foregroundColor(Color.red)
            .edgesIgnoringSafeArea(.top)
        MyContent()
    }
}

一旦我知道如何更新標題文本本身,我就會更新我的答案。

您可以使用SwiftUI-Introspect單獨設置它們,而不是設置會影響所有導航欄的appearance()

例子:

struct ContentView: View {
    var body: some View {
        NavigationView {
            ScrollView {
                Text("Hello world!")
            }
            .navigationTitle("Title")
        }
        .introspectNavigationController { nav in
            nav.navigationBar.barTintColor = .systemBlue
        }
    }
}

結果:

結果

肯定已經有一些很好的答案,但它們都只涵蓋部分工作:

  1. 來自@arsenius的絕佳解決方案 - 給出一個好的開始點

  2. 來自@EngageTheWarpDrive的優雅方式——這絕對提高了可用性

  3. 對於最新版本的 iOS 和 swiftUI @Thahir建議使用工具欄

很少有更多建議建議對UINavigationBar使用UIAppearence全局配置——因為對我來說,全局更改不是一個好主意,可能並不總是合適的。

我最終將所有提案合並到下一個代碼中:

  1. navigationBar配置創建NavigationControllerRepresentablemodifier

     struct NavigationControllerLayout: UIViewControllerRepresentable { var configure: (UINavigationController) -> () = { _ in } func makeUIViewController( context: UIViewControllerRepresentableContext<NavigationControllerLayout> ) -> UIViewController { UIViewController() } func updateUIViewController( _ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationControllerLayout> ) { if let navigationContoller = uiViewController.navigationController { configure(navigationContoller) } } } extension View { func configureNavigationBar(_ configure: @escaping (UINavigationBar) -> ()) -> some View { modifier(NavigationConfigurationViewModifier(configure: configure)) } } struct NavigationConfigurationViewModifier: ViewModifier { let configure: (UINavigationBar) -> () func body(content: Content) -> some View { content.background(NavigationControllerLayout(configure: { configure($0.navigationBar) })) } }
  2. 修改navigationBar以滿足您的要求(例如 bg 顏色和其他道具):

     extension UINavigationBar { enum Appearence { case transparent case defaultLight case colored(UIColor?) var color: UIColor { ... } var appearenceColor: UIColor { ... } var tint: UIColor { .... } var effect: UIBlurEffect? { .... } } func switchToAppearence(_ type: Appearence) { backgroundColor = type.color barTintColor = type.tint // for iOS 13+ standardAppearance.backgroundColor = type.appearenceColor standardAppearance.backgroundEffect = type.effect // u can use other properties from navBar also simply modifying this function } }
  3. 如您所見,這里我們肯定需要在ColorUIColor之間建立一些橋梁。 iOS 14開始 - 你可以只是UIColor.init(_ color: Color) ,但在iOS 14之前沒有這樣的方法,所以我最終得到了簡單的解決方案:

     extension Color { /// Returns a `UIColor` that represents this color if one can be constructed /// /// Note: Does not support dynamic colors var uiColor: UIColor? { self.cgColor.map({ UIColor(cgColor: $0) }) } }

這不適用於動態顏色

  1. 結果你可以使用它如下:

     // modifier to `NavigationView` .configureNavigationBar { $0.switchToAppearence(.defaultLight) }

希望這可能對某人有所幫助;)

我還沒有弄清楚如何在每個視圖的基礎上制作前景色,但我確實找到了一個簡單的背景色解決方法。

如果使用.inline標題,則可以在NavigationView頂部使用帶有矩形的VStack

NavigationView {
    VStack() {
        Rectangle()
            .foregroundColor(.red)
            .edgesIgnoringSafeArea(.top)
            .frame(height: 0)

        List {
            Text("Hello World")
            Text("Hello World")
            Text("Hello World")
        }
    }
    .navigationBarTitle("Hello World", displayMode: .inline)
    // ...

請注意矩形如何使用0.edgesIgnoringSafeArea(.top)的框架高度。

這是對我有用的解決方案。 您需要從作為 rootViewController 的 UINavigationController 開始。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        let nav = setupNavigationController()
        window.rootViewController = nav
        self.window = window
        window.makeKeyAndVisible()
    }
}

func setupNavigationController() -> UINavigationController {
    let contentView = ContentView()
    let hosting = UIHostingController(rootView: contentView)
    let nav = NavigationController(rootViewController: hosting)
    let navBarAppearance = UINavigationBarAppearance()
    navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
    navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
    navBarAppearance.backgroundColor = UIColor.black
    nav.navigationBar.standardAppearance = navBarAppearance
    nav.navigationBar.scrollEdgeAppearance = navBarAppearance
    nav.navigationBar.prefersLargeTitles = true
    return nav
}

然后在您的內容視圖中:

struct ContentView: View {

    @State private var isModalViewPresented: Bool = false

    var body: some View {
        List(0 ..< 10, rowContent: { (index) in
            NavigationLink(destination: DetailView()) {
                Text("\(index)")
            }
        })
        .navigationBarItems(trailing: Button("Model") {
            self.isModalViewPresented.toggle()
        })
        .sheet(isPresented: $isModalViewPresented, content: {
            ModalView()
        })
        .navigationBarTitle("Main View")
    }
}

如果您想在某些時候更改顏色,例如在模態視圖中,請使用此處給出的答案

struct ModalView: View {
    var body: some View {
        NavigationView {
           Text("Hello, World!")
           .navigationBarTitle("Modal View")
           .background(NavigationConfigurator { nc in
              nc.navigationBar.backgroundColor = UIColor.blue
              nc.navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
           })
       }
    }
}

你可以繼承 UINavigationController 來改變狀態欄的顏色

class NavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override var preferredStatusBarStyle: UIStatusBarStyle 
    {
        .lightContent
    }
}

主視圖 模態視圖

.foregroundColor(.orange) - изменяет внутренние представления NavigationView。

但是要更改導航視圖本身,您需要在init()中使用UINavigationBar Appearance() )

我一直在尋找這個問題,並找到了一篇關於的好文章。 我通過這篇文章修改了你的代碼並取得了成功。 在這里,我如何解決這個問題:

struct ContentView: View {
    
    init() {
        let coloredAppearance = UINavigationBarAppearance()
        
        // this overrides everything you have set up earlier.
        coloredAppearance.configureWithTransparentBackground()
        coloredAppearance.backgroundColor = .green
        coloredAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
        
        // to make everything work normally
        UINavigationBar.appearance().standardAppearance = coloredAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
    }
    
    var body: some View {
        NavigationView {
            List{
                ForEach(0..<15) { item in
                    HStack {
                        Text("Apple")
                            .font(.headline)
                            .fontWeight(.medium)
                            .lineLimit(1)
                            .multilineTextAlignment(.center)
                            .padding(.leading)
                            .frame(width: 125, height: nil)
                            .foregroundColor(.orange)
                        
                        
                        Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
                            .font(.subheadline)
                            .fontWeight(.regular)
                            .multilineTextAlignment(.leading)
                            .lineLimit(nil)
                            .foregroundColor(.orange)
                    }
                }
            }
            .navigationBarTitle(Text("TEST"))
        }
// do not forget to add this
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

你也可以在這里舉一些例子

我在我的獨立 Apple Watch 應用中遇到了這個限制。 盡管此修復程序在 SwiftUI 中並不嚴格,但我轉到了 Interface.storyboard 文件,選擇了托管控制器,選擇了右側的文件檢查器,然后在 Interface Builder Document 部分下設置了 Global Tint 旁邊的顏色。

13.4 更新

注意:第二天重新訪問,可能我的一些問題是由我的有點不標准的設置引起的:我仍在運行 mojave,但手動添加了 13.4 支持文件(通常只能通過 xcode 11.4 獲得,這需要 catalina )。 我之所以提到這一點,是因為我 / 也有一些標簽欄自定義顏色問題,但我只是注意到這些問題只有在我實際插入手機並從 xcode 運行應用程序時才會顯現出來。 如果我拔掉插頭,只是正常運行應用程序,我沒有看到標簽欄問題,所以導航欄問題可能有一些相似之處......

(我會將其添加為對上述 arsenius 答案(當前接受的答案)的評論,但我沒有代表,所以......)

我正在使用該解決方案,並且在 13.4 之前它一直運行良好,這似乎已經破壞了它,至少對我而言。 經過大量的視圖層次跟蹤,看起來他們改變了一些事情,使得隱式 UINavigationController 不再像解決方法中描述的那樣通過傳遞的 UIViewController 輕松訪問。 它仍然在那里(離樹很遠),我們只需要找到它。

為此,我們可以遍歷視圖層次結構,直到找到導航欄,然后像往常一樣在其上設置所需的參數。 這需要一個新的發現功能,以及 NavigationConfigurator 結構的一些小改動,以及它的實例化......

首先,發現功能:

func find_navbar(_ root: UIView?) -> UINavigationBar?
{
    guard root != nil else { return nil }

    var navbar: UINavigationBar? = nil
    for v in root!.subviews
    {   if type(of: v) == UINavigationBar.self { navbar = (v as! UINavigationBar); break }
        else { navbar = find_navbar(v); if navbar != nil { break } }
    }

    return navbar
}

修改 NavigationConfigurator 如下(請注意,我們不再關心傳入視圖,因為這不再可靠):

struct NavigationConfigurator: UIViewControllerRepresentable
{
    @EnvironmentObject var prefs: Prefs     // to pick up colorscheme changes

    var configure: () -> Void = {}
    func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController { UIViewController() }
    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) { self.configure() }
}

(在我的應用程序中,我有一個 Prefs 對象來跟蹤顏色等)

...然后,在實例化站點,執行以下操作:

MyView()
    .navigationBarTitle("List", displayMode: .inline)
    .navigationBarItems(trailing: navbuttons)
    .background(NavigationConfigurator {
        if self.prefs.UI_COLORSCHEME != Colorscheme.system.rawValue
        {   if let navbar = find_navbar(root_vc?.view)
            {   navbar.barTintColor = Colors.uicolor(.navbar, .background)
                navbar.backgroundColor = .black
                navbar.titleTextAttributes = [.foregroundColor: Colors.uicolor(.navbar, .foreground)]
                navbar.tintColor = Colors.uicolor(.navbar, .foreground)
            }
        }
    })

請注意,我在我的應用程序的其他地方捕獲了根視圖控制器,並在此處使用它傳遞給 find_navbar()。 您可能想以不同的方式進行操作,但是由於其他原因,我已經有了該變量……還有一些其他特定於我的應用程序的東西,例如與顏色相關的對象,但是您明白了。

https://stackoverflow.com/a/58427754/4709057這個答案有效,但如果您遇到navigationController 在明暗模式下為零的問題。 只需添加這個..不知道它為什么會起作用。

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.background = .blue
            nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
        })
    }
   .navigationViewStyle(StackNavigationViewStyle())
   .accentColor(.red)   <------- DOES THE JOB
  }
}

使用 SwiftUI 的 WatchOS 導航標題顏色
watchOS 的旁注是您不需要擺弄導航顏色。 這是您需要更改的 Watch Accent 顏色。 在您的項目中進入 WatchProjectName->Asset->Accent 並更改它在此處輸入圖像描述

https://developer.apple.com/documentation/watchkit/setting_the_app_s_tint_color

基於此https://stackoverflow.com/a/66050825/6808357 ,我創建了一個擴展,您可以在其中同時設置背景顏色和標題顏色。

import SwiftUI

extension View {
    
    /// Sets background color and title color for UINavigationBar.
    @available(iOS 14, *)
    func navigationBar(backgroundColor: Color, titleColor: Color) -> some View {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithTransparentBackground()
        appearance.backgroundColor = UIColor(backgroundColor)

        let uiTitleColor = UIColor(titleColor)
        appearance.largeTitleTextAttributes = [.foregroundColor: uiTitleColor]
        appearance.titleTextAttributes = [.foregroundColor: uiTitleColor]

        UINavigationBar.appearance().standardAppearance = appearance
        UINavigationBar.appearance().scrollEdgeAppearance = appearance
        
        return self
    }
}

以下是如何使用它:

var body: some View {
    NavigationView {
        Text("Hello world!") // This could be any View (List, VStack, etc.)
        .navigationTitle("Your title here")
        .navigationBar(backgroundColor: .blue, titleColor: .white)
    }
}

快樂編碼!

使用UINavigationBarAppearance做到這一點的新方法

extension UINavigationController {

    open override func viewDidLoad() {
        super.viewDidLoad()

        let standardAppearance = UINavigationBarAppearance()
        standardAppearance.backgroundColor = .blue
        standardAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        standardAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
        navigationBar.standardAppearance = standardAppearance
        navigationBar.compactAppearance = standardAppearance
        navigationBar.scrollEdgeAppearance = standardAppearance

    }}

如果您需要單獨的樣式用於compactAppearance ,則可以scrollEdgeAppearance

extension UINavigationController {

open override func viewDidLoad() {
    super.viewDidLoad()

    let standardAppearance = UINavigationBarAppearance()
    standardAppearance.backgroundColor = .blue
    standardAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
    standardAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]


    let compactAppearance = UINavigationBarAppearance()
    compactAppearance.backgroundColor = .red


    let scrollEdgeAppearance = UINavigationBarAppearance()
    scrollEdgeAppearance.backgroundColor = .yellow


    navigationBar.standardAppearance = standardAppearance
    navigationBar.compactAppearance = compactAppearance
    navigationBar.scrollEdgeAppearance = scrollEdgeAppearance

}}

更多閱讀

如果您不介意全局更改它,我發現進入資產目錄並設置 AccentColor 有效。

對我有用的解決方案是使用 UINavigationBarAppearance() 方法,然后將 .id() 添加到 NavigationView。 這將在顏色更改時自動重繪組件。

現在,您可以根據狀態引擎進行反應性顏色更改。

var body: some Scene {
  let color = someValue ? UIColor.systemBlue : UIColor.systemGray3

  let custom = UINavigationBarAppearance()
  custom.configureWithOpaqueBackground()
  custom.backgroundColor = color
  UINavigationBar.appearance().standardAppearance = custom
  UINavigationBar.appearance().scrollEdgeAppearance = custom
  UINavigationBar.appearance().compactAppearance = custom
  UINavigationBar.appearance().compactScrollEdgeAppearance = custom

  return WindowGroup {
    NavigationView {
      content
    }
      .id(color.description)
  }
}

該解決方案建立在不使用任何庫也不全局應用UINavigationBarAppearance的公認答案之上。

此解決方案通過添加 hack 解決了已接受答案的問題(例如不適用於初始視圖或不適用於大顯示模式)。

請注意,我個人不會在生產代碼中使用此 hack,但有趣的是,這些問題可以得到解決。 使用風險自負。

struct NavigationHackView: View {

    @State private var isUsingHack = false

    var body: some View {
        NavigationView {
            List {
                NavigationLink {
                    Text("Detail view")
                        .navigationTitle("Detail view")
                        .navigationBarTitleDisplayMode(.inline)
                } label: {
                    Text("Show details view")
                }
            }
            .navigationTitle("Hack!")
            .background(
                NavigationConfigurator { navigationController in
                    // required for hack to work
                    _ = isUsingHack
                    navigationController.navigationBar.navigationBarColor(.red, titleColor: .white)
                }
            )
            .onAppear {
                // required for hack to work
                DispatchQueue.main.async {
                    isUsingHack.toggle()
                }
            }
            // required for hack to work, even though nothing is done
            .onChange(of: isUsingHack) { _ in }
        }
    }
}

struct NavigationConfigurator: UIViewControllerRepresentable {

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

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

    func updateUIViewController(
        _ uiViewController: UIViewController,
        context: UIViewControllerRepresentableContext<NavigationConfigurator>
    ) {
        guard let navigationController = uiViewController.navigationController else {
            return
        }
        configure(navigationController)
    }
}

extension UINavigationBar {

    func navigationBarColor(
        _ backgroundColor: UIColor, 
        titleColor: UIColor? = nil
    ) {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = backgroundColor

        if let titleColor = titleColor {
            appearance.titleTextAttributes = [.foregroundColor: titleColor]
            appearance.largeTitleTextAttributes = [.foregroundColor: titleColor]
            // back button appearance
            tintColor = titleColor
        }

        standardAppearance = appearance
        scrollEdgeAppearance = appearance
        compactAppearance = appearance

        if #available(iOS 15.0, *) {
            compactScrollEdgeAppearance = appearance
        }
    }
}
Post iOS 14 easy way to do:

        protocol CustomNavigationTitle: View {
            associatedtype SomeView: View
            func customNavigationTitle(_ string: String) -> Self.SomeView
        }
        
        extension CustomNavigationTitle {
            func customNavigationTitle(_ string: String) -> some View {
                toolbar {
                    ToolbarItem(placement: .principal) {
                        Text(string).foregroundColor(.red).font(.system(size: 18))
                    }
                }
            }
        }
        
        extension ZStack: CustomNavigationTitle {}
    
    Suppose your root view of view is made with ZStack
    it can be utilised below way
    
    ZStack {
    }. customNavigationTitle("Some title")

演示

iOS 14開始,您可以擁有任何您想要的自定義視圖(包括具有自定義顏色和字體的自定義文本)

.navigationBarTitleDisplayMode(.inline)
.toolbar {
    ToolbarItem(placement: .principal) {
        VStack {
            Text("Yellow And Bold Title")
                .bold()
                .foregroundColor(.yellow)
        }
    }
}

您還可以從iOS 16設置導航欄顏色,例如:

.toolbarBackground(.red, in: .navigationBar)

我使用 ViewModifier 為導航欄應用自定義顏色。 我不能說下面的代碼修改了實際的導航欄,但我發現這個工作比其他工作更好。

與 UINavigationBar.appearance() 不同,它並不適用於所有視圖。

  • 創建一個 ViewModifer - 我使用了 ShapeStyle ,因此您可以將任何樣式應用於導航欄。 (如 - 漸變、顏色)
struct NavigationBarStyle<S: ShapeStyle>: ViewModifier {
    private var bgStyle: S
    private var viewBackgroundColor: Color
    
    init(_ bgStyle: S, viewBackgroundColor: Color) {
        self. bgStyle = bgStyle
        self.viewBackgroundColor = viewBackgroundColor
    }
    
    func body(content: Content) -> some View {
        ZStack {
            Color(UIColor.systemBackground)
                .ignoresSafeArea(.all, edges: .bottom)
            
            content
        }
        .background(bgStyle)
    }
}

extension View {
    func navigationBarStyle<S: ShapeStyle>(_ bgStyle: S, viewBackgroundColor: Color = Color(UIColor.systemBackground)) -> some View {
        modifier(NavigationBarStyle(bgStyle, viewBackgroundColor: viewBackgroundColor))
    }
}

注意 - 您必須在最頂部的視圖上應用此修改器才能工作。 例如 -

struct NewView: View {
    var body: some View {
        NavigationView {
            VStack {
                HStack {
                    Text("H Stack")
                }
                // .navigationBarStyle(Color.orange) not the right place
                Text("Hello World")
            }
            .navigationBarStyle(Color.orange) // right place to apply
        }
    }
}

struct ContentView: View {
    
    init() {
        UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor(Color("Golden"))]
     }
    
    var body: some View {
        NavigationView {
            List(movies) { movie in
                NavigationLink {
                    MovieDetail(movie: movie)
                } label: {
                    MovieCell(movie: movie)
                }
            }
            .navigationTitle("Movies")
        }
    }
}

使用 UINavigationBar.appearance().largeTitleTextAttributes 屬性更改導航欄標題顏色

我發現的最簡單的方法是:

init() {
    UINavigationBar.appearance().tintColor = UIColor.systemBlue
    }

除了 systemBlue,您還可以使用您希望的任何其他顏色。 您必須在“var body: some View {}”之外實現它。 您還可以添加:

@Environment(/.colorScheme) var colorScheme

init()之上,然后您可以使用 .dark 或 .light 在暗模式和亮模式下以您想要的方式更改顏色。 例子:

init() {
    UINavigationBar.appearance().tintColor = UIColor(colorScheme == .dark ? .white : Color(#colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)))
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM