I have looked at all the similar questions I could find and I have not found a solution to this problem.
I am setting the titleView property like this in viewDidLoad:
self.navigationItem.titleView = label
The view controller is part of a navigation stack. When you tap on a row in in the previous view controller it pushes this controller onto the stack. Completely normal UINavigationController stuff.
As this view controller begins to animate in, the label appears at the origin (top left) and then stays there until the view controller finishes animating and then it jumps (no animation) to the proper position in the middle of the nav bar.
After tapping on the back button the title view animates out correctly, just like a normal title would.
Here is the code in 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
Things I've tried:
Specify a frame: no change. Plus I don't want to specify a frame. I don't want to make assumptions about the height of the nav bar.
Moved it to
viewWillAppear: no change.Moved it to
viewDidAppear: better but still not right. The label does not appear at all until the animation is complete and then it appears where it should, no animation it just appears. The correct behaviour is to animate in from right to left like a normal title would.
This is easily reproducible with the Master-Detail project template in Xcode. If you want to try it just add the code above to the top of configureView() in DetailViewController.swift. In that template the navigation item's title is hardcoded into the storyboard. You can easily remove it by searching for "Detail". Click the result that says Navigation Item: Title = "Detail" and then remove the string from the Inspector pane.
Update
@synndicate's suggestion does work perfectly for the UILabel example above. But my real problem is with a UIStackView. When I use a stack view following the approach @synndicate suggests I get yet another animation problem. This time the title view starts sliding in but animates all the way to the origin. When the animation is finished it snaps to where it should be.
Here's the code in prepare(for:sender:) as @synndicate suggests...
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
Any further suggestions?
Also, this is Xcode 8 and iOS 10.
Update 2
I have discovered that the stack view code above animates perfectly (just like an ordinary title would) in viewDidLoad for a view controller where the root of the nav hierarchy is a UINavigationController. The problem occurs when the root of the nav hierarchy is a UISplitViewController.
So I guess I could update my question to this...
How do I configure a UIStackView that will be set on the navigationItem's titleView property where the root of the navigation hierarchy is a UISplitViewController?