Using Swift5.1.3, XCode11.3, iOS13.3,
I try to reposition a custom navigationBar titleView.
Creating the custom view and adding it to my navigationBar works fine. (see code below)
Here an example: Please only consider the DarkGray NavigationBar on top with a Name-Label and a yellow round Image. The label and image shall be moved in y-direction!
The example on the left, I have successfully running. The example on the right I try to achieve. But without luck so far.
There is one missing thing I am struggling with since 4 hours.
How do I adjust the y-position (or .topAnchor constant offset) of a custom navigationBar titleView ???
The crash-message says:
'Unable to activate constraint with anchors
<NSLayoutYAxisAnchor:0x6000033ac900 "UIStackView:0x7fdcced39ea0.top"> and
<NSLayoutYAxisAnchor:0x6000033644c0 "UIView:0x7fdcd412ba20.top"> because they
have no common ancestor. Does the constraint or its anchors reference items
in different view hierarchies? That's illegal.'
Here is my code (please note the comment with the many exclamation marks - that is the y-offset trial and crash position of my code):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// ...
// set up navigationItem and navigationController look and feeel
navigationController?.set_iOS12_lookAndFeel()
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
navigationItem.largeTitleDisplayMode = .always
// create NavigationBar.titleView StackView (consisting of a label and a button)
let titleStackView = UIStackView(frame: CGRect(origin: .zero, size: CGSize(width: self.view.bounds.width, height: 88.0)))
titleStackView.isUserInteractionEnabled = true
titleStackView.axis = .horizontal
titleStackView.alignment = .center
titleStackView.spacing = 10.0
// stackView label
let labelWidth: CGFloat = UIScreen.main.bounds.width - 16.0 - 10.0 - 36.0 - 16.0 // FullScreenWidth minus (Leading + Spacing + ButtonWidth + Trailing)
let label = UILabel()
label.font = AppConstants.Font.NavBar_TitleFont
label.text = self.profileName
label.textColor = .white
label.tintColor = .white
// position label
label.translatesAutoresizingMaskIntoConstraints = false
label.widthAnchor.constraint(equalToConstant: labelWidth).isActive = true
// stackView button
let buttonWidth: CGFloat = 36.0
let button = UIButton(frame: CGRect(origin: .zero, size: CGSize(width: buttonWidth, height: buttonWidth)))
button.setImage(self.profileImageView.image, for: .normal)
button.isUserInteractionEnabled = true
button.addTarget(self, action: #selector(self.callProfileBtnMethod), for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 36, height: 36)
button.layer.cornerRadius = button.frame.size.width / 2
button.layer.masksToBounds = false
button.clipsToBounds = true
// position button
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: buttonWidth).isActive = true
button.heightAnchor.constraint(equalToConstant: buttonWidth).isActive = true
// add label and button to stackView
titleStackView.addArrangedSubview(label)
titleStackView.addArrangedSubview(button)
// position titleStackView
titleStackView.translatesAutoresizingMaskIntoConstraints = false
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Here the code crashes !!!!!!!
titleStackView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100.0).isActive = true
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// position cockpitHeaderView (equal in size and position to titleStackView)
let cockpitHeaderView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: self.view.bounds.width, height: 88.0)))
cockpitHeaderView.backgroundColor = .green
cockpitHeaderView.isUserInteractionEnabled = true
cockpitHeaderView.addSubview(titleStackView)
cockpitHeaderView.leadingAnchor.constraint(equalTo: titleStackView.leadingAnchor, constant: 0.0).isActive = true
cockpitHeaderView.topAnchor.constraint(equalTo: titleStackView.topAnchor, constant: 0.0).isActive = true
cockpitHeaderView.trailingAnchor.constraint(equalTo: titleStackView.trailingAnchor, constant: 0.0).isActive = true
cockpitHeaderView.bottomAnchor.constraint(equalTo: titleStackView.bottomAnchor, constant: 0.0).isActive = true
// finally replace NavBar title by custom cockpitHeaderView
self.title = ""
self.navigationItem.titleView = cockpitHeaderView
}
How can I move the titleView correctly ???