Arsh Bhullar
Arsh Bhullar

Reputation: 61

custom back button in navigation in iOS

I know this question has been asked before but nothing worked for me and I had to ask it again. I want an image as my back button in navigation bar, just want to change the appearance of the back button. I don't want to add a button and add selectors for it.

I tried the following code:

let backImage = UIImage(named: "Back_button")

        let backAppearance = UIBarButtonItem.appearance()
        backAppearance.setBackButtonBackgroundImage(backImage, for: .normal, barMetrics: .default)

        navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage
        navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItem.Style.plain, target: nil, action: nil)

I also tried setting the back image and back mask using storyboard but both these approaches place a black circle on my back image.

I tried setting another image as back mask by setting its alpha content equal to zero using the code but it didn't work either.

please help.

Upvotes: 2

Views: 9424

Answers (6)

Abhishek Biswas
Abhishek Biswas

Reputation: 31

first embed the viewcontroller in navigation view controller and then at viewDidLoad function use this code for making a UIBarButton item.

override func viewDidLoad() {
    super.viewDidLoad()
    navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "arrowshape.left.fill"), style: .done, target: self, action: #selector(backAction(_ :)))
}

After that in action of bar button item define like this

@objc func backAction(_ sender: UIBarButtonItem){
      // uncomment according to your need
      // removing the current screen from view controller stack

      // self.navigationController?.popViewController(animated: true)

      // going to root view controller 
      // self.navigationController?.popToRootViewController(animated: true)
      // works only when the view controller is push modelly
      self.dismiss(animated: true, completion: nil)
}

Upvotes: 0

Malky Shlomowitz
Malky Shlomowitz

Reputation: 11

I used this code to customize the back button on only one of my views:

    self.navigationController?.navigationBar.topItem?.backButtonTitle = ""
    let backButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(goBack))
    navigationItem.leftBarButtonItem = backButton

@objc func goBack() {
    self.navigationController?.popViewController(animated: true)
}

Upvotes: 1

Capella
Capella

Reputation: 1011

This code works with Swift 5.

let backButton: UIButton = UIButton()
backButton.setImage(UIImage(named: "back"), for: UIControl.State())
backButton.addTarget(self, action:#selector(SearchResultsViewController.onBack), for: UIControl.Event.touchUpInside)
let leftBarButtonItem = UIBarButtonItem(customView: backButton)
navigationItem.leftBarButtonItem = leftBarButtonItem

Upvotes: 1

Tej Patel
Tej Patel

Reputation: 119

Simply Add Below Methods in Your ViewController :

func setLeftBarBackItem() {
    
    let leftBarBackItem = UIBarButtonItem(image: #imageLiteral(resourceName: "imgBack"), style: .plain, target: self, action: #selector(self.clickToBtnBackItem(_:)))
    self.navigationItem.leftBarButtonItem = leftBarBackItem
    
}

func clickToBtnBackItem(_ sender: UIBarButtonItem) {
    view.endEditing(true)
    
    _ = navigationController?.popViewController(animated: true)
    
}

func setTranspertNavigation()
{    
    self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
    self.navigationController?.navigationBar.shadowImage = UIImage()
    self.navigationController?.navigationBar.isTranslucent = true
    self.navigationController?.view.backgroundColor = .clear
}

Inside Your ViewController's ViewDidLoad Method, Set backButton As :

    self.navigationController?.isNavigationBarHidden = false
    AppDelegate.shared().setupNavigationBar()
    setLeftBarBackItem()
    setTranspertNavigation()
    self.title = "Title Here"

Upvotes: -1

Habin Lama
Habin Lama

Reputation: 559

let backButton = UIBarButtonItem()
backButton.title = "Back"
backButton.image = UIImage(named: "Back_button")
self.navigationController?.navigationBar.topItem?.backBarButtonItem = backButton

You can do this to customize your Back button. And you don't have to worry about adding selectors.

Upvotes: 2

emrcftci
emrcftci

Reputation: 3514

  • Create a custom class for define navigation bar traits
  • Create an extension to UINavigationController for configure it

import UIKit

private final class MyNavigationBarTraits {

  public var backIndicatorImage: UIImage?
  public var backIndicatorTransitionMaskImage: UIImage?

  public func apply(to navigationBar: UINavigationBar) {
    navigationBar.backIndicatorImage = backIndicatorImage
    navigationBar.backIndicatorTransitionMaskImage = backIndicatorTransitionMaskImage
  }

  public init(navigationBar: UINavigationBar) {
    backIndicatorImage = navigationBar.backIndicatorImage
    backIndicatorTransitionMaskImage = navigationBar.backIndicatorTransitionMaskImage
  }
}

public typealias Callback<T> = (_: T) -> Void

public extension UINavigationController {

  private struct AssociationKeys {
    static var navigationBarTraits = "ws_nc_navigationBarTraits"
  }

  private var navigationBarTraits: MyNavigationBarTraits? {
    get {
      return objc_getAssociatedObject(self, &AssociationKeys.navigationBarTraits) as? MyNavigationBarTraits
    }
    set {
      objc_setAssociatedObject(self, &AssociationKeys.navigationBarTraits, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
  }

  func configureBar(block: Callback<UINavigationBar>) {
    navigationBarTraits = MyNavigationBarTraits(navigationBar: navigationBar)
    block(navigationBar)
  }

  func resetBar() {
    navigationBarTraits?.apply(to: navigationBar)
    navigationBarTraits = .none
  }
}

And then you can configure your navigation bar in your ViewController's viewWillAppear (for example tintColor)

  public override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    navigationController?.configureBar { navigationBar in
      // You can customize your navigation bar in here!
      navigationBar.tintColor = .red
    }
  }

If you want to use this customization just in one View Controller you should reset bar in your View Controller's viewWillDisappear

  public override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    navigationController?.resetBar()
  }

Upvotes: -1

Related Questions