如何更改导航栏返回按钮的字体?

42

如何更改导航栏返回按钮的字体。

返回按钮是“返回”或上一个视图控制器的标题。

我以为这个 viewDidLoad 会起作用:

navigationController?.navigationItem.leftBarButtonItem?.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "FONTNAME", size: 20)!], forState: UIControlState.Normal)

但是leftBarButton?可选项会返回nil


您希望应用程序中的每个条形按钮项的字体都相同,还是只有返回按钮相同? - Ian
我假设你会在应用程序委托中提供设置,了解这两种解决方案实际上都很有用 :) - Kyle Goslan
6个回答

72
如果您需要在整个应用程序中(例如每个导航按钮)完全更改字体样式,则首选方法是使用UIBarButtonItem.appearance()代理。

示例代码片段如下:

SWIFT 3.0+

//make sure font name u use below *actually* exists in the system !
//if it doesn't app will crash because we're force unwrapping an optional (see below) !!!
let customFont = UIFont(name: "customFontName", size: 17.0)!
UIBarButtonItem.appearance().setTitleTextAttributes([NSFontAttributeName: customFont], for: .normal)

当涉及到字体样式的时候,把代码片段放在AppDelegate.swift文件的开头是明智的选择,因为每次应用程序启动时都需要进行字体样式化。此外,您可以将此代码放置在任何其他地方(例如Presenter类)中,以进行UI样式化和自定义。一旦执行了该代码,所有的BarButtons都将在其之后被自定义。


但是作为一个真正的Swift程序员,您应该首先可选解包您的字体,如果找不到或加载字体时遇到任何其他可能的问题,最终回退到系统字体。

var textAttributes: [String:Any]

//custom font setup
let fontColor = UIColor.purple
let barItemCustomFont = UIFont(name: "", size: 14)  //note we're not forcing anything here

//can we use our custom font 
if let customFont = barItemCustomFont {
    //hooray we can use our font 
    textAttributes = [NSForegroundColorAttributeName: fontColor, NSFontAttributeName: customFont]
} else {
    // not found -> omit setting font name and proceed with system font
    textAttributes = [NSForegroundColorAttributeName: fontColor]
}

//finally
UIBarButtonItem.appearance().setTitleTextAttributes(textAttributes, for: .normal)

实际应用举例

在实际的应用程序中,通常需要自定义UINavigationBarUIBarButton字体样式(除其他参数外),以使它们在视觉上保持一致。 下面是一个方便的stylizeNavigationFontOfMyAmazingApp函数,您可以使用:

    func stylizeNavigationFontOfMyAmazingApp() {
        //custom font
        let customFont = UIFont(name: "someFancyFont", size: 16)!  //note we're force unwrapping here

        //navigation bar coloring:
        UINavigationBar.appearance().tintColor = UIColor.white
        UINavigationBar.appearance().barTintColor = UIColor.blue

        //unique text style:
        var fontAttributes: [String: Any]
        fontAttributes = [NSForegroundColorAttributeName: UIColor.red, NSFontAttributeName: customFont]

        //navigation bar & navigation buttons font style:
        UINavigationBar.appearance().titleTextAttributes = fontAttributes
        UIBarButtonItem.appearance().setTitleTextAttributes(fontAttributes, for: .normal)

   }

使用appearance()代理的优点

  • 只需两行代码,即可为您的应用程序/项目中的每个 UIBarButtonItem设置样式。
  • 您可以混合几个类的appearance()代理,以获得真正独特的视觉风格。
  • 如果您需要更进一步的定制控制,则可以在具体的UIBarButtonItem实例上再次重新自定义每个按钮(例如,在特定实例上放置自定义视图、按钮、图像等)。

参考资料

Apple文档关于appearance协议的说明。


32

刚测试了您的代码,看起来那一行返回 nil 的原因实际上是因为 name: "FONTNAME" 返回了 nil。所以如果您将 name 属性设置为有效的字体名称,则代码应该可以无误运行——即使 navigationController?.navigationItem.leftBarButtonItem 明确设置为 nil。

但不管怎样,正如我通过测试所看到的那样,这行代码不会给您带来您想要的结果。前面导航控制器的可选项不应该存在,因为它访问的是您的 UINavigationController 而不是当前视图。直接使用 UIViewControllernavigationItem 属性来直接访问其 leftBarButtonItem 即可,例如:

let backButton = UIBarButtonItem(title: "< Back", style: UIBarButtonItemStyle.Plain, target: self, action: "goBack")
navigationItem.leftBarButtonItem = backButton
navigationItem.leftBarButtonItem?.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Chalkduster", size: 20)!], forState: UIControlState.Normal)

编辑:从您在此答案下发布的评论中,似乎您实际上并不想设置leftBarButtonItem,而是backBarButtonItem,因为您不想实现除返回到上一个视图控制器之外的自定义操作。

因此,在那个上一个视图控制器中(即您想要显示自定义返回按钮项目的视图之前),您可以这样设置没有操作的自定义返回按钮:

let backButton = UIBarButtonItem(title: "< Back", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
backButton.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Chalkduster", size: 20)!], forState: UIControlState.Normal)
navigationItem.backBarButtonItem = backButton

嘿,谢谢你的答复。我知道使用无效的字体名称会导致崩溃,但我只是将其放在那里作为占位符。我想我只需要编辑已经存在的按钮上的setTitleTextAttributes(),因为它已经能够导航回到上一个视图,你的解决方案有效,但现在我需要设置它的操作,这似乎有点冗长,因为本质上已经有了... - Kyle Goslan
那就不要使用 leftBarButtonItem,使用 backBarButtonItem。我马上更新并解释一下... - Lyndsey Scott

22

如果您想将此更改应用于您的所有应用程序,您可以使用以下代码:

Swift 4

我已经将以下几行代码添加到AppDelegate.swift文件中的application函数中:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       UINavigationBar.appearance().titleTextAttributes = [
            NSAttributedStringKey.font: UIFont(name: "IranSansMobile", size: 20)!
        ]

        UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedStringKey.font: UIFont(name: "IranSansMobile", size: 15)!], for: UIControlState.normal)

  return true
}

Swift 3

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    UINavigationBar.appearance().titleTextAttributes = [
        NSFontAttributeName: UIFont(name: "IranSansMobile", size: 20)!
    ]

    UIBarButtonItem.appearance().setTitleTextAttributes([NSFontAttributeName: UIFont(name: "IranSansMobile", size: 15)!], for: UIControlState.normal)


    return true
}

3
还需要将属性 for: .selected 设置为选中状态,否则按钮在按下时会显示原始字体。 - Serdnad
2
还需要在“for: .highlighted”中保持相同的字体以便在触摸按下时使用。 - Gobot

8

iOS 13和Swift 5.1:

let fontAttr = [NSAttributedString.Key.font: \*your font*\]

let buttonAppearance = UIBarButtonItemAppearance()
buttonAppearance.normal.titleTextAttributes = fontAttr

let navbarAppearance = UINavigationBarAppearance()
navbarAppearance.buttonAppearance = buttonAppearance
UINavigationBar.appearance().standardAppearance = navbarAppearance

这对我有用!对于在iOS 13上看到导航栏按钮上的破碎字体的任何人,将其包装在#ifavailable子句中对我起了作用,并在else块中放入旧的方法(适用于iOS 12及以下版本)。 - Orlando G Rodriguez
这个可以用,但是它覆盖了我的标题字体,有什么想法吗? - Nico S.
3
谢谢,我想知道为什么在我的iOS13代码中setTitleTextAttribute不起作用。buttonAppearance.normal.titleTextAttributes = fontAttr是我需要的。 - mushcraft
对我没用。我们需要在哪个生命周期方法中编写这个? - Deepak Thakur

3

当你确定已经设置了UIBarButtonItem后,可以执行以下操作:

self.navigationItem.leftBarButtonItem!.title = "myTitle"

要改变颜色,你可以按照以下步骤操作:

self.navigationItem.leftBarButtonItem!.tintColor = UIColor.redColor()

当您在Storyboard中没有设置它时,可以执行以下操作:
self.navigationItem.leftBarButtonItem = UIBarButtonItem()

更改字体,请按以下步骤操作:
self.navigationItem.leftBarButtonItem!.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "FONTNAME", size: 20)!], forState: .Normal)

也许我应该提醒您不要使用self.navigationController,因为当设置navigationController的按钮时,它们不会显示在屏幕上,因此屏幕上的按钮必须是在故事板中设置的self.navigationItem...


谢谢您的回复,但是在这个视图中我没有UIBarButtonItem,它是从上一个视图继承而来的。即使使用您回答中的最后两行代码(不带self),它仍然返回nil。 - Kyle Goslan
实际上,当您手动设置它时,它不可能返回nil。您说它是从前一个视图继承的 - 您能给我们提供这些信息吗? - borchero

3

SWIFT 3

    UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName: UIFont(name: "Open Sans", size: 15)!,NSForegroundColorAttributeName: UIColor.white]
    UIBarButtonItem.appearance().setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Open Sans", size: 15)!], for: UIControlState.normal)

2
有必要重复已经在这里回答过的一切吗? - Vexy

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