1

我看过所有类似的问题,我可以找到,我还没有找到解决这个问题的方法。NavigationItem的titleView不能正确动画

我设置titleView属性像这样在viewDidLoad

self.navigationItem.titleView = label 

视图控制器是一个导航堆栈的一部分。当你点击前一个视图控制器中的一行时,它会将该控制器压入堆栈。完全正常的UINavigationController的东西。

当这个视图控制器开始动画时,标签出现在原点(左上角),然后停留在那里直到视图控制器完成动画,然后它跳到(没有动画)到正确的位置导航栏。

点击后退按钮后,标题视图会正常动画,就像普通标题一样。

这里是viewDidLoad代码:

let label = UILabel(frame: CGRect.zero) 
label.textAlignment = .center 
label.translatesAutoresizingMaskIntoConstraints = false 
label.backgroundColor = .red 
label.text = "test" 
label.sizeToFit() 
self.navigationItem.titleView = label 

事情我已经尝试:

  • 指定一个框架:没有变化。另外我不想指定一个框架。我不想对导航栏的高度进行假设。

  • 将其移动到viewWillAppear:没有变化。

  • 将其移动到viewDidAppear:更好但仍不正确。在动画完成之前,标签一直没有出现,然后出现在它应该出现的位置,没有刚刚出现的动画。正确的行为是像正常的标题那样从右向左动画。

这很容易重现Xcode中的主 - 明细项目模板。如果你想尝试,只需将上面的代码添加到configureView()的顶部DetailViewController.swift。在该模板中,导航项目的标题被硬编码到故事板中。您可以通过搜索“详细信息”轻松删除它。单击Navigation Item: Title = "Detail"的结果,然后从“检查器”窗格中删除该字符串。


更新

@ synndicate的建议,并为上述UILabel例子很好地工作。但我真正的问题是与UIStackView。当我使用@synndicate方法使用堆栈视图时,我发现还有另一个动画问题。这一次,标题视图开始滑入,但一直到原点的动画。动画完成后,它会捕捉到它应该在的位置。

下面是prepare(for:sender:)代码为@synndicate建议...

let label = UILabel(frame: CGRect.zero) 
label.textAlignment = .center 
label.translatesAutoresizingMaskIntoConstraints = false 
label.backgroundColor = .red 
label.text = "test" 
let stackView = UIStackView(frame: CGRect.zero) 
stackView.translatesAutoresizingMaskIntoConstraints = false 
stackView.addArrangedSubview(label) 
stackView.sizeToFit() 
controller.navigationItem.titleView = stackView 

任何进一步的建议?

此外,这是Xcode 8和iOS 10。

更新2

我们已经发现,上述堆栈视图代码动画完美(就像一个普通的标题会)在viewDidLoad为一个视图控制器,其中NAV层次结构的根是一个UINavigationController。当导航层次结构的根目录为UISplitViewController时,会发生此问题。

所以我想我可以更新我对这个问题......

如何配置将在navigationItemtitleView财产在导航层次结构的根是UISplitViewController设置一个UIStackView

回答

0

在将视图控制器推入堆栈之前,是否可以将代码移至?

例如在主从项目MasterViewController.swift

override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if segue.identifier == "showDetail" { 
      if let indexPath = tableView.indexPathForSelectedRow {      

       let object = objects[indexPath.row] as! NSDate 
       let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController 
       controller.detailItem = object 
       controller.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem 
       controller.navigationItem.leftItemsSupplementBackButton = true 

       let label = UILabel() 
       label.textAlignment = .center 
       label.backgroundColor = .red 
       label.text = "test" 
       label.sizeToFit() 

       controller.navigationItem.titleView = label 

      } 
     } 
    } 
+0

针对其添加到您的更新,在这一点上,我建议你不得不重构和子类UINavigationController在那里你设置你的titleView那里。然后在将来'准备(for:sender)'调用你可以设置特定于控制器的文本被推送 – synndicate

0

如果你想在stackView出现在导航堆栈的特定视图控制器,只需在视图控制器

self.view.addSubview(stackView) 
+0

正确。但它不会在任何地方。我试图在导航项目的titleView中使用堆栈视图。所有细节都在上面。 –

+0

为什么你需要将它添加为'titleView'? 'titleView'是为了在整个导航过程中持续使用_only_。 –

+0

我想在导航栏的标题中添加多个标签。我的理解是,每个视图控制器都可以像“title”一样设置navigationItem的'titleView'。 –