Swift Custom NavBar Back Button Image and Text

后端 未结 12 1292
谎友^
谎友^ 2021-01-30 10:40

I need to customise the look of a back button in a Swift project.

Here\'s what I have:

Here\'s what I want:

I\'ve tried creating my own UIBarButtonItem

相关标签:
12条回答
  • 2021-01-30 10:54

    This worked for me on iOS 13 using swift 5. Just hide the original back button and add a new navigation left bar button item with an action.

    navigationItem.hidesBackButton = true
    navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "backBtn"), style: .plain, target: self, action: #selector(back(sender:)))
    
    @objc func back(sender: UIBarButtonItem) {
        self.navigationController?.popViewController(animated:true)
    }
    
    0 讨论(0)
  • 2021-01-30 10:55

    swift 4

    In my case, I needed to have only the image of the button, without any text. I hope this will be useful to someone.

    let imgBackArrow = UIImage(named: "back_arrow_32")
    
    navigationController?.navigationBar.backIndicatorImage = imgBackArrow
    navigationController?.navigationBar.backIndicatorTransitionMaskImage = imgBackArrow
    
    navigationItem.leftItemsSupplementBackButton = true
    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: self, action: nil)
    

    For iOS 12 you can do

    func setNavigationBar() {
    
        self.navigationItem.setHidesBackButton(true, animated:false)
    
        //your custom view for back image with custom size
        let view = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
        let imageView = UIImageView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
    
        if let imgBackArrow = UIImage(named: "icn_back_arrow") {
            imageView.image = imgBackArrow
        }
        view.addSubview(imageView)
    
        let backTap = UITapGestureRecognizer(target: self, action: #selector(backToMain))
        view?.addGestureRecognizer(backTap)
    
        let leftBarButtonItem = UIBarButtonItem(customView: view ?? UIView())
        self.navigationItem.leftBarButtonItem = leftBarButtonItem
    }
    
    @objc func backToMain() {
        self.navigationController?.popViewController(animated: true)
    }
    
    0 讨论(0)
  • 2021-01-30 11:02

    You can do something like that:

    let yourBackImage = UIImage(named: "back_button_image")
    self.navigationController?.navigationBar.backIndicatorImage = yourBackImage
    self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
    self.navigationController?.navigationBar.backItem?.title = "Custom"
    

    Your image will only have one color though

    0 讨论(0)
  • 2021-01-30 11:02

    Just replace the backButton with a custom rightBarButtonItem

    let backImage = UIImage(named: "BackBtn")?.withRenderingMode(.alwaysOriginal)
        navigationItem.leftBarButtonItem = UIBarButtonItem(image: backImage, style: .plain, target: self, action: #selector(popnav))
    
        @objc func popnav() {
        self.navigationController?.popViewController(animated: true)
    }
    
    0 讨论(0)
  • 2021-01-30 11:03

    Having a button in Navigation Bar with Image AND Text is quite hard. Especially after they have introduced a new headache with UIBarButtonItem position in iOS 11: iOS 11 - UIBarButtonItem horizontal position

    You can make either button with image or a button with text, but not a button with both of those. I even tried two UIBarButtonItems together, one with image and other with text - it still doesn't look good at all and their UIStackView can't be easily accessed for modification.

    Unexpectedly I found a plain simple solution:

    1) design the button as view in Interface Builder. In my case it is inside target UIViewController and accessible via IBOutlet for simplicity

    2) set Leading Space constraint for the image to be negative, you might also want to set view's background color to .clear.

    3) use it:

    @IBOutlet var backButtonView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let backButton = UIBarButtonItem(customView: self.backButtonView)
        self.backButtonView.heightAnchor.constraint(equalToConstant: 44).isActive = true // if you set more than you'll get "Unable to simultaneously..."
        self.backButtonView.widthAnchor.constraint(equalToConstant: 75).isActive = true
        self.navigationItem.leftBarButtonItem = backButton
    }
    

    That's it. No need to use the trick with negative spacer for iOS 10 or the trick with imageInsets for iOS 11 (which works only if you have image and doesn't work for image+text, BTW).

    0 讨论(0)
  • 2021-01-30 11:06

    Note: Please remember that the back button belongs to the the source ViewController and not to the destination ViewController. Thus, the modification needs to be done in the source VC, which is reflected to all the view in the navigation controller

    Code Snippet:

    let backImage = UIImage(named: "icon-back")
    
    self.navigationController?.navigationBar.backIndicatorImage = backImage
    
    self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage
    
    /*** If needed Assign Title Here ***/
    self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
    
    0 讨论(0)
提交回复
热议问题