ios SwiftUI 更新导航栏标题颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/56505528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:54:15  来源:igfitidea点击:

SwiftUI update navigation bar title color

iosnavigationbarswiftui

提问by Prashant Tukadiya

How to change the navigation bar title color in SwiftUI

如何在 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)
            }

I have tried with .foregroundColor(.orange)but it is not working

我试过,.foregroundColor(.orange)但它不起作用

also tried .navigationBarTitle(Text("TEST").color(.orange))

也试过 .navigationBarTitle(Text("TEST").color(.orange))

Any help ?

有什么帮助吗?

回答by arsenius

It is notnecessary to use .appearance()to do this globally.

这是不是必须使用.appearance()要做到这一点全球。

Although SwiftUI does not expose navigation styling directly, you can work around that by using UIViewControllerRepresentable. Since SwiftUI is using a regular UINavigationControllerbehind the scenes, the view controller will still have a valid .navigationControllerproperty.

尽管 SwiftUI 不直接公开导航样式,但您可以使用UIViewControllerRepresentable. 由于 SwiftUIUINavigationController在幕后使用常规,视图控制器仍将具有有效.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)
        }
    }

}

And to use it

并使用它

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

修改导航栏

回答by Anjali Kevadiya

In SwiftUI, you can not change the navigationTitleColor directly. You have to change UINavigation's appearance in init()like this,

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

I hope it will work. Thanks!!

我希望它会起作用。谢谢!!

回答by Dragos

I have developed a small sample of a custom SwiftUI navigation that can provide full visual customisation and programatic navigation. It can be used as a replacement for the NavigationView.

我开发了一个自定义 SwiftUI 导航的小示例,它可以提供完整的视觉定制和程序导航。它可以用作 NavigationView 的替代品。

Here is the NavigationStack class that deals with currentView and navigation stack:

这是处理 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()
    }
}

You can have a look here:for the full example with explanation:

您可以在此处查看:有关说明的完整示例:

PS: I am not sure why this one was deleted. I think it answer the question as it is a perfect functional alternative to NavigationView.

PS:不知道为什么删了这个。我认为它回答了这个问题,因为它是 NavigationView 的完美功能替代品。

回答by Andreas Pardeike

If you have your content as

如果你有你的内容

struct MyContent : View {
...
}

then you can put it like this inside a navigation view with a red background:

然后你可以把它像这样放在一个带有红色背景的导航视图中:

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

I will update my answer as soon as I know how to update the title text itself.

一旦我知道如何更新标题文本本身,我就会更新我的答案。

回答by Imran

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

回答by kdion4891

I still haven't figured out how to do the foreground color on a per-view basis, but I did figure out a simple workaround for the background color.

我仍然没有弄清楚如何在每个视图的基础上制作前景色,但我确实为背景色找到了一个简单的解决方法。

If using an .inlinetitle, you can just use a VStackwith a rectangle at the top of the NavigationView:

如果使用.inline标题,您可以只使用VStack带有顶部矩形的 a NavigationView

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)
    // ...

Note how the rectangle uses a frame height of 0and .edgesIgnoringSafeArea(.top).

注意矩形是如何使用的帧的高度0.edgesIgnoringSafeArea(.top)

回答by Austin Conlon

I hit this limitation in my independent Apple Watch app. Although this fix isn't strictly in SwiftUI, I went to the Interface.storyboard file, selected the hosting controller, selected the File inspector on the right, then set the color next to Global Tint under the Interface Builder Document section.

我在我的独立 Apple Watch 应用中遇到了这个限制。尽管此修复程序在 SwiftUI 中并不严格,但我转到了 Interface.storyboard 文件,选择了托管控制器,选择了右侧的文件检查器,然后在 Interface Builder Document 部分下设置了 Global Tint 旁边的颜色。

回答by ShigaSuresh

Use Below Code for Color Customization in SwiftUI

在 SwiftUI 中使用以下代码进行颜色自定义

This is for main body background color:-

这是主体背景颜色:-

struct ContentView: View {

var body: some View {

 Color.red
.edgesIgnoringSafeArea(.all)

 }

}

enter image description here

在此处输入图片说明

For Navigation Bar:-

对于导航栏:-

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

    }

    }

  }

enter image description here

在此处输入图片说明

For Other UI Elements Color Customization

对于其他 UI 元素颜色自定义

struct ContentView: View {

@State var msg = "Hello SwiftUI"

var body: some View {

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

    }
 }

enter image description here

在此处输入图片说明

回答by rnr-a-np

update for 13.4

13.4 更新

note: revisiting this the next day, it may be possible that some of my issues were caused by my somewhat nonstandard setup: i am still running mojave, but have manually added the 13.4 support files (normally available only via xcode 11.4, which requires catalina). i mention this because i am/was also having some tab bar custom color issues, but i just noticed that those are only manifesting when i have the phone actually plugged in and am running the app from xcode. if i unplug, and just run the app normally, i am not seeing the tab bar issues, so it may be possible that the nav bar issue had some similarity ...

注意:第二天重温这个问题,我的一些问题可能是由我的一些非标准设置引起的:我仍在运行 mojave,但手动添加了 13.4 支持文件(通常只能通过 xcode 11.4 获得,这需要 catalina )。我提到这一点是因为我/也有一些标签栏自定义颜色问题,但我只是注意到这些问题只有在我实际插入手机并从 xcode 运行应用程序时才会出现。如果我拔掉插头,然后正常运行应用程序,我没有看到标签栏问题,所以导航栏问题可能有一些相似之处......

(i would add this as a comment on arsenius' answer (the currently accepted one) above, but i don't have the rep, so ...)

(我会将此添加为对上面 arsenius 的回答(目前接受的回答)的评论,但我没有代表,所以......)

i was using that solution, and it was working perfectly up until 13.4, which seems to have broken it, at least for me. after a lot of view hierarchy tracing, it looks like they changed things such that the implicit UINavigationController is no longer easily accessible via the passed UIViewController as described in the workaround. it's still there though (pretty far up the tree), we just have to find it.

我正在使用该解决方案,并且它在 13.4 之前一直运行良好,这似乎已经破坏了它,至少对我而言。经过大量视图层次结构跟踪后,看起来他们改变了一些东西,使得隐式 UINavigationController 不再容易通过传递的 UIViewController 访问,如变通方法中所述。它仍然在那里(在树上很远的地方),我们只需要找到它。

to that end, we can just walk the view hierarchy until we find the navbar, and then set the desired parameters on it, as usual. this necessitates a new discovery function, and some minor changes to the NavigationConfigurator struct, and its instantiation ...

为此,我们只需遍历视图层次结构,直到找到导航栏,然后像往常一样在其上设置所需的参数。这需要一个新的发现功能,并对 NavigationConfigurator 结构体进行一些细微的更改,及其实例化...

first up, the discovery function:

首先,发现功能:

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
}

modify the NavigationConfigurator as follows (note that we no longer care about passing in a view, since that's no longer reliable):

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

(in my app, i have a Prefs object which keeps track of colors, etc.)

(在我的应用程序中,我有一个 Prefs 对象可以跟踪颜色等)

... then, at the instantiation site, do something like this:

...然后,在实例化站点,执行如下操作:

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

note that i capture the root view controller elsewhere in my app, and use it here to pass to find_navbar(). you might want to do it differently, but i already have that variable around for other reasons ... there's some other stuff there specific to my app, e.g., the color-related objects, but you get the idea.

请注意,我在应用程序的其他地方捕获了根视图控制器,并在此处使用它传递给 find_navbar()。你可能想以不同的方式来做,但由于其他原因我已经有了这个变量......还有一些其他特定于我的应用程序的东西,例如,与颜色相关的对象,但你明白了。

回答by Phil Cole

Here is the solution that worked for me. You need to start off with a UINavigationController as the rootViewController.

这是对我有用的解决方案。您需要从 UINavigationController 作为 rootViewController 开始。

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
}

and then in your content view:

然后在您的内容视图中:

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

and if you want to change the color at some point, such as in a modal view, use the answer given here

如果您想在某个时候更改颜色,例如在模态视图中,请使用此处给出的答案

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

you can subclass UINavigationController to change the status bar color

您可以继承 UINavigationController 来更改状态栏颜色

class NavigationController: UINavigationController {

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

    override var preferredStatusBarStyle: UIStatusBarStyle 
    {
        .lightContent
    }
}

Main ViewModal View

主视图模态视图