iOS 12 中的自定义导航标题

Posted

技术标签:

【中文标题】iOS 12 中的自定义导航标题【英文标题】:Custom Navigation Title in iOS 12 【发布时间】:2018-11-20 22:02:21 【问题描述】:

我正在尝试在 ios 应用上实现自定义导航标题。

故事板如下所示:

我想要自定义导航标题的地方是最后一个视图(消息视图),因为我使用图像和文本,这意味着我需要自定义宽度和高度。如果我在viewDidLoad 中这样做,就需要这个:

let rect = CGRect(x: 0, y:0, width: 150, height: 88)
titleView = UIView(frame: rect)
......
titleView?.addSubview(imageView)
......
titleView?.addSubview(label)
navigationItem.titleView = titleView

标题的高度被屏蔽到 44pt。

但我如何做到的是将子视图添加到导航栏:

var navigationBar: MessagesNavigationBar? 
    guard let navigationBar = navigationController?.navigationBar as? MessagesNavigationBar else 
        return nil
    
    return navigationBar

viewDidLoad

let rect = CGRect(x: 0, y:0, width: 150, height: 88)
titleView = UIView(frame: rect)
......
titleView?.addSubview(imageView)
......
titleView?.addSubview(label)
navigationBar?.addSubview(titleView!)

但问题是当我离开视图时我必须删除子视图,否则我添加的任何内容也会出现在表格视图中。

override func viewWillDisappear(_ animated: Bool) 
    super.viewWillDisappear(animated)
    if navigationBar != nil 
        titleView?.removeFromSuperview()
    

这让我觉得我做的不对,当我离开对话时,我发现很难为这些子视图添加淡出动画。 (即 iOS 上的原生消息应用)。

那么在 iOS 12 中创建自定义标题导航栏的正确方法是什么?

场景

【问题讨论】:

“由于需要这个,我不能在 viewDidLoad 中使用类似的东西”你为什么不能呢?这是正常且正确的做法…… 对不起,我含糊不清,我编辑了这个问题。所以,如果我使用navigationItem.titleView = titleView,我无法更改titleView 的高度,默认为44。 【参考方案1】:

创建您的自定义 titleView 并将其分配给 navigationItem.titleView 是您想要的。在旧系统(iOS 11 之前)上,您可能只需要在 titleView 上调用 sizeToFit()

这样就可以创建这个titleView

斯威夫特

override func viewDidLoad() 
    super.viewDidLoad()


    let imageView = UIImageView()
    NSLayoutConstraint.activate([
        imageView.heightAnchor.constraint(equalToConstant: 20),
        imageView.widthAnchor.constraint(equalToConstant: 20)
    ])
    imageView.backgroundColor = .red
    
    let titleLabel = UILabel()
    titleLabel.text = "Custom title"
    
    let hStack = UIStackView(arrangedSubviews: [imageView, titleLabel])
    hStack.spacing = 5
    hStack.alignment = .center
    
    navigationItem.titleView = hStack

Obj-C

- (void)viewDidLoad 
    [super viewDidLoad];
    
    UIImageView *imageView = [[UIImageView alloc] init];
    [NSLayoutConstraint activateConstraints:@[
        [imageView.heightAnchor constraintEqualToConstant:20],
        [imageView.widthAnchor constraintEqualToConstant:20]
    ]];
    imageView.backgroundColor = [UIColor redColor];

    UILabel *titleLabel = [[UILabel alloc] init];
    titleLabel.text = @"Custom title";

    UIStackView *hStack = [[UIStackView alloc] initWithArrangedSubviews:@[imageView, titleLabel]];
    hStack.spacing = 5;
    hStack.alignment = UIStackViewAlignmentCenter;
    
    self.navigationItem.titleView = hStack;

您可能还需要设置正确的自动布局约束或使用UIStackView

【讨论】:

sizeToFit() 自从 iOS 11 以来就无法正常工作,据我在其他 *** 上阅读的答案,我第一次尝试使用它,因为默认高度是 44,但我没有找到改变的方法它。 可能你的约束没有定义titleView的大小。 我没有任何约束,因为它只是一个导航控制器 -> 表格控制器 -> 视图控制器 + 导航栏。我也在问题中添加了带有场景的打印件。顺便说一句,sizeToFit 方法甚至没有被调用。 titleView 内部需要约束...顺便说一句。你是对的,因为不需要 iOS 11 sizeToFit() 我已经编辑了原始答案,所以它更清楚了【参考方案2】:

这些行对标题视图的大小没有影响:

let rect = CGRect(x: 0, y:0, width: 150, height: 88)
titleView = UIView(frame: rect)

取而代之(或另外)给你的标题视图一个宽度约束和一个高度约束。这就是运行时知道你想要什么大小的方式。

【讨论】:

以上是关于iOS 12 中的自定义导航标题的主要内容,如果未能解决你的问题,请参考以下文章

*某些* iOS 8 版本中的自定义导航项的内部不一致异常

iOS:带有面包屑路径的自定义导航栏?

Gatsbyjs 中的自定义导航栏

SwiftUI:导航链接中的自定义标签显示为灰色

创建导航栏的自定义实现

iOS 上的自定义模板系统