iOS 11 - 使用大标题模式时的 UINavigationItem titleView
iOS 11 - UINavigationItem titleView when using Large Titles mode
我正在尝试了解这是一个错误还是预期的行为。
在 iOS 10 和更早的时候,我们可以使用 navigationItem.titleView
.
设置自定义标题
在 iOS 11 上,当设置我们的 navigationItem.largeTitleDisplayMode = .always
和设置 navigationItem.titleView = <Some cool UIButton>
时,它显示 both 正常的导航标题栏和大导航标题。
插图:
总结一下:
我们如何在大型导航标题上使用自定义 titleView?
编辑:这是预期的结果:
我找不到这方面的任何文档,所以我玩了一下。好像在iOS11,你就不能把那个title做成按钮,在左边大显示了。
我不知道这是一个错误还是预期的结果,因为它似乎是一个新功能。最新的 (iOS 11) Human Interface Guidelines (HIG) 将较大的标题标签讨论为一种为用户提供清晰上下文的方式。 HIG 还讨论了按钮之间的 space。但是,没有讨论使用按钮 作为 标题。
为了重新创建,我设置了一个单视图项目。我将视图控制器嵌入到导航控制器中。
在ViewController.swift
的viewDidLoad
中,我添加了这段代码:
let titleButton = UIButton(type: .roundedRect)
titleButton.setTitle("Hello Button!", for: UIControlState.normal)
let navController = parent as! UINavigationController
navController.navigationBar.topItem!.title = "Hello???"
navController.navigationBar.topItem!.titleView = titleButton
navController.navigationBar.prefersLargeTitles = true
这最终看起来像你的例子。
如果我:
将 .title
设置为空字符串,或注释行:导航栏被拉伸,并且没有标题文本显示(或在 Interface Builder 中设置的标题文本显示)
备注.prefersLargeTitles
,或设置为false
:navbar为正常高度,显示按钮,但不显示标题文字。
注释掉 titleView
行,AND:
- 将
.prefersLargeTitles
设置为 true
:title
文本在左侧显示较大,并且导航栏的高度被拉伸。
- 将
.prefersLargeTitles
设置为false
:title
文本显示在顶部中央,导航栏为正常高度。
更新: link 至 sample project on GitHub
通过使用 UINavigationBar
的子类并手动更改视图层次结构,我能够用自定义视图替换导航栏大标题:
@interface MYNavigationBar : UINavigationBar
@end
@implementation MYNavigationBar
// ...
- (void)layoutIfNeeded
{
[self setupTitle];
[super layoutIfNeeded];
}
- (void)setupTitle
{
// UINavigationBar
// -> ...
// -> _UINavigationBarLargeTitleView
// -> UILabel << Big Title Label
// -> UIView
// -> UILabel << Big Title Label animating from back button during transitions
for (UIView *view in self.subviews) {
NSString *className = NSStringFromClass(view.classForCoder);
if ([className containsString:@"LargeTitleView"]) {
for (UIView *view2 in view.subviews) {
if ([view2 isKindOfClass:[UILabel class]]) {
[self convertLabel:(UILabel *)view2];
}
for (UIView *view3 in view2.subviews) {
if ([view3 isKindOfClass:[UILabel class]]) {
[self convertLabel:(UILabel *)view3];
}
}
}
}
}
}
- (void)convertLabel:(UILabel*)label
{
// I kept the original label in the hierarchy (with the background color as text color)
// and added my custom view as a subview.
// This allow the transformations applied to the original label to be also applied to mine.
}
请注意,Apple 可能 会因为这个技巧而拒绝您的应用。
我正在尝试了解这是一个错误还是预期的行为。
在 iOS 10 和更早的时候,我们可以使用 navigationItem.titleView
.
设置自定义标题
在 iOS 11 上,当设置我们的 navigationItem.largeTitleDisplayMode = .always
和设置 navigationItem.titleView = <Some cool UIButton>
时,它显示 both 正常的导航标题栏和大导航标题。
插图:
总结一下:
我们如何在大型导航标题上使用自定义 titleView?
编辑:这是预期的结果:
我找不到这方面的任何文档,所以我玩了一下。好像在iOS11,你就不能把那个title做成按钮,在左边大显示了。
我不知道这是一个错误还是预期的结果,因为它似乎是一个新功能。最新的 (iOS 11) Human Interface Guidelines (HIG) 将较大的标题标签讨论为一种为用户提供清晰上下文的方式。 HIG 还讨论了按钮之间的 space。但是,没有讨论使用按钮 作为 标题。
为了重新创建,我设置了一个单视图项目。我将视图控制器嵌入到导航控制器中。
在ViewController.swift
的viewDidLoad
中,我添加了这段代码:
let titleButton = UIButton(type: .roundedRect)
titleButton.setTitle("Hello Button!", for: UIControlState.normal)
let navController = parent as! UINavigationController
navController.navigationBar.topItem!.title = "Hello???"
navController.navigationBar.topItem!.titleView = titleButton
navController.navigationBar.prefersLargeTitles = true
这最终看起来像你的例子。
如果我:
将
.title
设置为空字符串,或注释行:导航栏被拉伸,并且没有标题文本显示(或在 Interface Builder 中设置的标题文本显示)备注
.prefersLargeTitles
,或设置为false
:navbar为正常高度,显示按钮,但不显示标题文字。注释掉
titleView
行,AND:- 将
.prefersLargeTitles
设置为true
:title
文本在左侧显示较大,并且导航栏的高度被拉伸。 - 将
.prefersLargeTitles
设置为false
:title
文本显示在顶部中央,导航栏为正常高度。
- 将
更新: link 至 sample project on GitHub
通过使用 UINavigationBar
的子类并手动更改视图层次结构,我能够用自定义视图替换导航栏大标题:
@interface MYNavigationBar : UINavigationBar
@end
@implementation MYNavigationBar
// ...
- (void)layoutIfNeeded
{
[self setupTitle];
[super layoutIfNeeded];
}
- (void)setupTitle
{
// UINavigationBar
// -> ...
// -> _UINavigationBarLargeTitleView
// -> UILabel << Big Title Label
// -> UIView
// -> UILabel << Big Title Label animating from back button during transitions
for (UIView *view in self.subviews) {
NSString *className = NSStringFromClass(view.classForCoder);
if ([className containsString:@"LargeTitleView"]) {
for (UIView *view2 in view.subviews) {
if ([view2 isKindOfClass:[UILabel class]]) {
[self convertLabel:(UILabel *)view2];
}
for (UIView *view3 in view2.subviews) {
if ([view3 isKindOfClass:[UILabel class]]) {
[self convertLabel:(UILabel *)view3];
}
}
}
}
}
}
- (void)convertLabel:(UILabel*)label
{
// I kept the original label in the hierarchy (with the background color as text color)
// and added my custom view as a subview.
// This allow the transformations applied to the original label to be also applied to mine.
}
请注意,Apple 可能 会因为这个技巧而拒绝您的应用。