如何在SwiftUI中更改.navigationBarTitle字体?

18

我正在使用Xcode 11中的SwiftUI,我想用以下代码更改NavigationBarTitle字体:

.navigationBarTitle (Text("Navigation Bar Title"), displayMode: .inline)
    .font(.subheadline)

但是什么都没有发生。有任何建议或评论吗?


类似但尚未得到回答的问题:https://dev59.com/C1MI5IYBdhLWcg3wUp02 - Prashant Tukadiya
其中一种方法是使用Appearance API,或者等待SwiftUI的新版本。 - Prashant Tukadiya
6个回答

22

在SwiftUI中,目前我们无法直接更改navigationBarTitle字体,但您可以通过以下方式更改navigationBar的外观:

struct YourView: View {
    init() {
        //Use this if NavigationBarTitle is with Large Font
        //UINavigationBar.appearance().largeTitleTextAttributes = [.font : UIFont(name: "Georgia-Bold", size: 20)!]

        //Use this if NavigationBarTitle is with displayMode = .inline
        UINavigationBar.appearance().titleTextAttributes = [.font : UIFont(name: "Georgia-Bold", size: 20)!]
    }
    var body: some View {
        NavigationView {
            Text("Hello World!")
            //.navigationBarTitle("TEST")
            .navigationBarTitle (Text("TEST"), displayMode: .inline)
        }
    }
}

我希望它能对你有所帮助。谢谢!!


3
在我的情况下,这在iOS 16及以上版本上无法正常工作。 - Darkwonder
1
是的,iOS 16 给出了警告 - “只有未经样式处理的文本才能与 navigationTitle 一起使用”。 - KAMIKAZE

3

目前还无法使用.font修饰符更改navigationBarTitle的字体(已在Xcode 11-Beta2中测试)。

但是,您可以构建自己的自定义navigationBarView,并完全访问其任何子视图,如下所示:

struct NavigationBarView: View {

    var body: some View {

        VStack(spacing: 0) {
            Rectangle()
                .foregroundColor(Style.Color.navigationBarColor)
                .edgesIgnoringSafeArea(.top)
                .frame(height: 0)

            Rectangle()
                .foregroundColor(Style.Color.navigationBarColor)
                .frame(height: 64)
            .overlay(
                HStack() {
                    Image("close")
                    Spacer()

                    Text("سفر به سلامت")
                        .font(Style.Font.navigationTitle)
                        .color(Style.Color.darkTextColor)
                        .multilineTextAlignment(.center)

                    Spacer()
                    Image("menu")
                }
            )

            Spacer()
        }
        .edgesIgnoringSafeArea(.horizontal)
    }
}

请注意,使用此实现方式将失去LargeTitleStyle

3

我认为你需要创建一个NavigationBarBuilder。

struct NavigationBarBuilder: UIViewControllerRepresentable {

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

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

        UIViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationBarBuilder>) {

        if let navigationController = uiViewController.navigationController{
            self.build(navigationController)
        }
    }
}

你可以在你的内容视图中使用它。

struct ContentView: View {
    var body: some View {
        NavigationView {
            Text("")
                .navigationBarTitle("Türkiye", displayMode: .inline)
                .background(NavigationBarBuilder {navigationController in
                    navigationController.navigationBar.barTintColor = .red
                    navigationController.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]
                })
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

祝你好运...


2
在SwiftUI 5中,UINavigationBar.appearance().titleTextAttributes不起作用。您需要使用以下其中一项来更改标题的字体:
        init () {
            UINavigationBar.appearance().largeTitleTextAttributes = [.font : UIFont(name: "Georgia", size: 20)!]
            // OR
            UINavigationBar.appearance().largeTitleTextAttributes = [.font:UIFont.preferredFont(forTextStyle:.text-style)]
        }

在UIFont.TextStyle文档中可以找到.text-style,例如。

.caption
.body
.title1
.title2
.title3
etc

更新1(回答评论区关于精确代码的问题)

struct ContentView: View {

    init () {
        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = .center
        
        UINavigationBar.appearance().largeTitleTextAttributes = [.font:UIFont.preferredFont(forTextStyle:.title2),
                                                                 .foregroundColor:UIColor.systemBlue,
                                                                 .paragraphStyle: paragraph
                                                                ]

然后在主体部分我有这个。你可能需要注意displayMode参数。

// Body is in the same ContentView struct. Settings from init will be used in navigationBarTitle
// listView() is just a custom function returning a SwiftUI's List()

var body: some View {


        NavigationView {
            
        listView()
            .navigationBarTitle(
                Text(self.accts.selCount <= 0 ? "Accounts" : "\(self.accts.selCount) selected")
                ,
                displayMode:.large)

我没有看到这个工作。尝试在父NavigationView的init和子视图中。你能分享一个简短的例子,确切地说明这个init在哪里吗? - Ryan
谢谢,但我不确定我是否理解了。最后一个块具有一个ViewBuilder体和三个AnyViews以及内部导航视图的TabView。不清楚init会放在哪里...在由func listView生成的视图中还是其他地方。您能否编写一个可构建的单个View结构?我确实看到全局覆盖方法起作用:https://stackoverflow.com/a/67172529/14433738 - Ryan
@Ryan 这是非常标准的。'init' 是某个 "struct ContentView: View..." 的构造函数。ContentView 在 SceneDelegate.scene 函数中用于设置初始视图。'var body' 定义了相同 ContentView 结构中内容的 UI。不确定什么让你感到困惑。init 和 'var body' 都在同一个 ContentView 类中定义。在 body 中,你只需要注意一件事:navigationBarTitle。 - Oleg Gryb
稍微更新了一下答案,以明确'init'和'var body'都在同一个ContentView结构体中,该结构体是所有视图的根。 - Oleg Gryb
这条评论有助于澄清意图。只是提醒一下,来自一个使用SwiftUI制作了一些实际应用程序的读者,代码格式/语法存在各种奇怪的问题,包括分割三元运算符和括号和方括号可能混淆或未复制等,这使得猜测正在发生什么。也许是SO在粘贴时做了一些事情。感谢提出的解决方案路线并花时间编辑,谢谢。 - Ryan
是的,格式不好。我通过删除不必要的细节来简化第二部分。希望现在更易读了。 - Oleg Gryb

0
在我的情况下,以上的答案并没有起到作用。 但是一下的代码运行良好。
let appearance = UINavigationBarAppearance()
        
appearance.titleTextAttributes = [.font : UIFont(name: "Georgia-Bold", size: 20)!]

0
尝试像下面这样添加导航标题,然后享受吧。在[Xcode 14.3 - ios 16.4]中进行了测试。
NavigationView { // <1>
    Text("Hello, SwiftUI!")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar { // <2>
            ToolbarItem(placement: .principal) { // <3>
                VStack {
                    Text("Title").font(.headline)
                    Text("Subtitle").font(.subheadline)
                }
            }
        }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接