原文链接: sarunw.com/posts/new-w…
作者: @sarunw
在 iOS14,长按后退按钮会显示一个导航历史的菜单。我们已经在前一篇文章中讨论了这个问题和解决方案。虽然在那篇文章中的解决方案能够实际运行,但我很高兴 Apple 在 iOS14 beta 3 中添加了一个新的 NavigationItem 属性来解决这个问题。
建议在阅读本文章之前先阅读一下前一篇文章来了解问题所在,这样你就会明白为什么 Apple 要添加这个新的属性了。
backButtonDisplayMode
这个新的属性是 backButtonDisplayMode ,他被用来控制后退按钮如何展示他的 title。
@available(iOS 14.0, *)
open var backButtonDisplayMode: UINavigationItem.BackButtonDisplayMode
他的类型是 UINavigationItem.BackButtonDisplayMode
public enum BackButtonDisplayMode : Int {
/// Default mode, uses an appropriate title, followed by a generic title (typically 'Back'), then no title.
case `default` = 0
/// Generic titles only. Ignores .title and .backButtonTitle (but *not* .backBarButtonItem.title).
case generic = 1
/// Don't use a title, just the back button indicator image.
case minimal = 2
}
Sources of back button title
由于 backButtonDisplayMode 定义了后退按钮的 title 的来源,那我们来看一下现在有哪些方式能决定后退按钮的 title。
A view controller title or navigation item title
当 backButtonTitle 或 backBarButtonItem 没有被指明时,一个 ViewController 的 title 或 navigationItem.title 会被用作后退按钮的 title。(译者注:两者是同级的,同时设置时后执行的则为 ViewController 的 title)
class AViewController: UIViewController {
override func viewDidLoad() {
title = "Title A"
// or
navigationItem.title = "Title A"
}
}
Back button title
你可以通过 navigationItem.backButtonTitle 来直接设置后退按钮的 title。他会覆盖你设置的 UIViewController.title 或 UIViewController.navigationItem.title。
class AViewController: UIViewController {
override func viewDidLoad() {
title = "Title A"
navigationItem.backButtonTitle = "backButtonTitle A"
}
}
Back bar button item
在这些设置 title 的方法中,优先级最高的是 navigationItem.backBarButtonItem。这会覆盖任何你设置过的 title, navigationItem.backButtonTitle ,navigationItem.backBarButtonItem。
class AViewController: UIViewController {
override func viewDidLoad() {
title = "Title A"
navigationItem.backButtonTitle = "backButtonTitle A"
navigationItem.backBarButtonItem = UIBarButtonItem(title: "backBarButtonItem A", style: .plain, target: nil, action: nil)
}
}
BackButtonDisplayMode.default
这就是在 iOS14 以前你所见到的后退按钮的样式。他右边显示的 title 就是你在导航历史中会见到的标题。
BackButtonDisplayModel.generic
这个模式使用 Back(返回) 来作为你的后退按钮的 title。但在导航历史中他会使用 title,navigationItem.title 或 navigationItem.backButtonTitle 来作为标题。
class AViewController: UIViewController {
override func viewDidLoad() {
title = "Title A"
// or
navigationItem.title = "Title A"
navigationItem.backButtonDisplayMode = .generic
}
}
但后退按钮使用的是"Back"(返回)
上述规则同样适用与 navigationItem.backButtonTitle,但是这不会影响你通过navigationItem.backBarButtonItem 设置的标题。
class AViewController: UIViewController {
override func viewDidLoad() {
title = "Title A"
navigationItem.backButtonTitle = "backButtonTitle A"
navigationItem.backBarButtonItem = UIBarButtonItem(title: "backBarButtonItem A", style: .plain, target: nil, action: nil)
navigationItem.backButtonDisplayMode = .generic
}
}
BackButtonDisplayModel.minimal
这个模式不会在后退按钮的右侧显示一个 title,只会有一个箭头图标。导航历史中依然会使用title,navigationItem.title 或 navigationItem.backButtonTitle 来作为标题。就像.generic 一样,他不会影响你通过 navigationItem.backBarButtonItem 设置的标题。
class AViewController: UIViewController {
override func viewDidLoad() {
title = "Title A"
navigationItem.backButtonTitle = "backButtonTitle A"
navigationItem.backButtonDisplayMode = .minimal
}
}
Summary
| 标题来源 | BackButtonDisplayMode | 后退按钮 Title | 导航历史标题 |
|---|---|---|---|
| title, navigationItem.title or navigationItem.backButtonTitle | default | 标题来源 or 位置不够时使用 Back(返回) | 标题来源 |
| title, navigationItem.title or navigationItem.backButtonTitle | generic | "Back"(返回) | 标题来源 |
| title, navigationItem.title or navigationItem.backButtonTitle | minimal | 无 | 标题来源 |
| navigationItem.backBarButtonItem | default | 标题来源 or 位置不够时使用 Back(返回) | 标题来源 |
| navigationItem.backBarButtonItem | generic | 标题来源 or 位置不够时使用 Back(返回) | 标题来源 |
| navigationItem.backBarButtonItem | minimal | 标题来源 or 位置不够时使用 Back(返回) | 标题来源 |
Conclusion
backButtonDisplayMode 是一个在 iOS14 加入的不错的 API,我们现在能更好的控制后退按钮的 title 样式。
下面的代码会使 ViewController 的标题为 "Title A",后退按钮后没有 title,导航历史中的标题显示为"Title in history stack A"。
class AViewController: UIViewController {
override func viewDidLoad() {
title = "Title A"
navigationItem.backButtonTitle = "Title in history stack A"
navigationItem.backButtonDisplayMode = .minimal
}
}
这比我们在前一篇文章文章中做的 hack 看起来清爽了许多。