简体   繁体   中英

Align UINavigationBar title with button on the right like iOS13 Messages app

What is the best way to align right bar button items with left title in UINavigationBar ? (now I have the icons at the top right corner)

CASE 1: Right Icons only

If you only need to set the two right barButton icons Call the method below your viewDidLoad.

Explanation: You create two navBar button items then you separate them with a fixed spacer which you choose the spacing based on design spec, pass the image names of your icons which should be correctly sized based on Apples HIG ( I found 22 x 22px ~ 25 x 25px to be a great custom range but you can change based on your design spec.

   private func setUpRightNavBarIcons() {
         let editBarButtonItem = UIBarButtonItem(image: UIImage(named: "yourEditIconImageName")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(editButtonItemTapped))
         let moreBarButtonItem = UIBarButtonItem(image: UIImage(named: "yourMoreIconImageName")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(moreBarButtonItemTapped))
        let fixedSpacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
        fixedSpacer.width = 22
        self.navigationItem.rightBarButtonItems = [fixedSpacer,editBarButtonItem, moreBarButtonItem]
    }

    @objc private func moreBarButtonItemTapped() {
        print("moreBarButtonItemTapped")
        // TODO: - Add your logic
    }

    @objc private func editButtonItemTapped() {
        print("editButtonItemTapped")
           // TODO: - Add your logic
    }

CASE 2: Left Title/Large Title

There are two ways which you can use to get that alignment.

  1. Set it yourself by calling the following method on your ViewDidLoad
private func setLeftAlignedNavBarTitle() {
   let label = UILabel()
   label.sizeToFit()
   let titleAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 25, weight: .bold), NSAttributedString.Key.foregroundColor: UIColor.black]
   label.attributedText = NSAttributedString(string: "Message", attributes: titleAttributes)
   /// Make this label as leftBar Button
   let leftButtonView = UIBarButtonItem(customView: label)
   navigationItem.leftBarButtonItem = leftButtonView
}

2.Another alternative is to allow large titles on viewDidLoad and get it for free, like so: -

navigationController?.navigationBar.prefersLargeTitles = true

NB: - If you need it on the right then use the first approach and set it as rightBarButtonItem.

maybe there is a more correct and optimal solution, but it is suitable for me. Do not be alarmed by the syntax, I use SnapKit

  1. Create button or view
lazy private var settingsButton = UIButton().then {
        $0.setImage(Image.settings, for: .normal)
    }
  1. override viewDidAppear(_ animated: Bool)
navigationController?.navigationBar.subviews.forEach { subview in
    let stringFromClass = NSStringFromClass(subview.classForCoder)
    guard stringFromClass.contains("UINavigationBarLargeTitleView") else { return }
    subview.subviews.forEach { label in
        guard label is UILabel else { return }
        subview.addSubview(settingsButton)
        settingsButton.snp.makeConstraints{
            $0.top.equalTo(label)
            $0.right.equalToSuperview().offset(-14)
            $0.height.width.equalTo(35)
        }
    }
}

  1. set UIScrollViewDelegate and in scrollViewDidScroll method get ahead of the navigationBar state and then hide / show the UIBarButtonItem

Result

screenshot

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM