KylaM26
KylaM26

Reputation: 17

rightBarButtonItem appearing in the middle

The rightbarbuttonitem is not appearing on the right side of the navigation bar. I want the navigation bar to look similar to the one in the "App Store"

I have tried doing this in the storyboard and in the code, setting the image content mode, clipping to bounds, and giving it a frame.

I have also been looking at solutions online and none of them have worked for me. Any help or suggestions would be appreciated, thanks.

Here are some screenshots: enter image description hereenter image description here

import UIKit


class KYSearchBarController: UISearchController {

    override init(searchResultsController: UIViewController?) {
        super.init(searchResultsController: searchResultsController)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    // Call in view did appear
    func CustomizeSearchBar() {
        // Changing color of text in textfield.
        let textfieldInsideBar = self.searchBar.value(forKey: "searchField") as? UITextField
        textfieldInsideBar?.textColor = .darkGray

        // Chaning placeholder
        let textfieldLbl = textfieldInsideBar?.value(forKey: "placeholderLabel") as? UILabel
        textfieldLbl?.textColor = .darkGray
        textfieldLbl?.textAlignment = .center

        // Icon customization
        let glassIcon = textfieldInsideBar?.leftView as? UIImageView
        glassIcon?.image = #imageLiteral(resourceName: "icon")
        glassIcon?.image?.withRenderingMode(.alwaysTemplate)
        glassIcon?.tintColor = .darkGray

        // Centering textfield text
        textfieldInsideBar?.textAlignment = .center

        let clearButton = textfieldInsideBar?.value(forKey: "clearButton") as! UIButton
        clearButton.setImage(UIImage(named: "icon1"), for: .normal)
        clearButton.tintColor = .darkGray
    }
}

extension UIView {
    func MakeRound() {
        self.layer.cornerRadius = self.frame.width / 5.0
    }
}

class ViewController: UIViewController, UISearchBarDelegate {

    let searchController = KYSearchBarController(searchResultsController: nil)

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = false

        let userimage = UIImageView(image: UIImage(named: "person1"))
        userimage.frame = CGRect(x: 60, y: 0, width: 50, height: 50)
        userimage.clipsToBounds = true
        userimage.layer.masksToBounds = true
        userimage.contentMode = .scaleAspectFit
        userimage.MakeRound()

        let rightBarButton = UIBarButtonItem(customView: userimage)
        navigationItem.rightBarButtonItem = rightBarButton

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
        searchController.CustomizeSearchBar()
    }

}


Upvotes: 0

Views: 930

Answers (2)

mona
mona

Reputation: 63

I ran into the same issue when I was using a very large image for my UIBarButtonItem.

Once I resized my image to a smaller size, it was appropriately placed at the right hand side of the navigation bar. It looks like you are having the same issue.

Alternatively, since starting from iOS 11 navigation bar uses autolayout, replacing the line

userimage.frame = CGRect(x: 60, y: 0, width: 50, height: 50)

with the below should also do the trick:

userimage.widthAnchor.constraint(equalToConstant: 50).isActive = true
userimage.heightAnchor.constraint(equalToConstant: 50).isActive = true

Upvotes: 1

lukaskasa
lukaskasa

Reputation: 673

  1. Add the userimage property to make it accessible inside the ViewController.
class ViewController: UIViewController, UISearchBarDelegate {

   let searchController = KYSearchBarController(searchResultsController: nil)

   let userimage = UIImageView(image: UIImage(named: "person1"))

}
  1. Add the makeRound() function call to viewWillLayoutSubviews().
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        userimage.makeRound()
    }
  1. Update the makeRound() function to make a circle.
extension UIView {
    func makeRound() {
        self.layer.cornerRadius = self.frame.width / 2.0
    }
}
  1. Add a method to add the necessary constraints.
func setupConstraints() {
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = false
    guard let navigationBar = self.navigationController?.navigationBar else { return }
    navigationBar.addSubview(userimage)
    userimage.clipsToBounds = true
    userimage.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        userimage.rightAnchor.constraint(equalTo: navigationBar.rightAnchor, constant: -16),
        userimage.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: -12),
        userimage.heightAnchor.constraint(equalToConstant: 40),
        userimage.widthAnchor.constraint(equalTo: userimage.heightAnchor)
    ])
}
  1. Setup a gesture recognizer for the UIImageView and implementation for it.
    func setUpGestureRecognizer() {
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(profile))
        userimage.isUserInteractionEnabled = true
        userimage.addGestureRecognizer(tapGestureRecognizer)
    }

    @objc func profile() {
        // Your implementation
    }
  1. Update viewDidLoad() with the method call.
    override func viewDidLoad() {
        super.viewDidLoad()
        // Setup constraints
        setupConstraints()
        setUpGestureRecognizer()
    }

Upvotes: 1

Related Questions