Nike Kov
Nike Kov

Reputation: 13718

Back UIBarButtonItem appearance remove text and change image

I've watched a lot of questions like this and didn't find an answer for my question.

That how i do now:

APPDELEGATE (didFinishLaunchingWithOptions)

// Text
let barButtonItem = UIBarButtonItem.appearance()
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: UIControlState.normal)
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: UIControlState.highlighted)

// Image
let backImage = UIImage(named: "arrow_left"
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage

And this almost fit to what i need, but the screen title shifted to the right as there is an invisible back button text. And it definetly is (the root controller's title has 9 characters length): enter image description here

The question is: How to change image, hide text and keep standart back action for every appearance of back button in ios 9.0 ?

Upvotes: 2

Views: 2061

Answers (7)

LLIAJLbHOu
LLIAJLbHOu

Reputation: 1313

Create an extension for UINavigationItem

extension UINavigationItem {
    func backBarButtonItem() -> UINavigationItem {
        return UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
    }
}

Upvotes: 0

Stewart Lynch
Stewart Lynch

Reputation: 995

You should watch Mark Moeykens' youtube series on this. He is IMHO one of the best YouTube presenters for UI Design and implementation in Swift.

The play list is https://www.youtube.com/playlist?list=PLHDMmeIMXj8WyvlX5uFmppVn2Pm0bXVr7

Upvotes: 0

Nike Kov
Nike Kov

Reputation: 13718

According to https://stackoverflow.com/a/16831482/5790492 there is a way to do this without appearance.

Swift 3.0

extension UIViewController {
    func setupCustomBackButton() {
        if let controllersCount = navigationController?.viewControllers.count, controllersCount > 1 {
            let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: 12, height: 20))
            backButton.setBackgroundImage(UIImage(named: "arrow_left"), for: .normal)
            backButton.contentMode = .left
            let backButtonItem = UIBarButtonItem(customView: backButton)
            backButton.addTarget(self, action: #selector(self.popCurrentViewController), for: .touchUpInside)
            navigationItem.leftBarButtonItem = backButtonItem
            navigationItem.hidesBackButton = true
        }
    }

    func popCurrentViewController() {
        navigationController?.popViewController(animated: true)
    }
}

Upvotes: 1

Stas Volskiy
Stas Volskiy

Reputation: 451

I can suggest you 2 options. Both require BaseViewController class as a superclass of all your view controllers.

  1. If you are ok with native back button image, just want to remove back button text you can use this subclass:

    class BaseViewController: UIViewController {
        var navigationTitle: String = ""
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            if !navigationTitle.isEmpty {
                navigationItem.title = navigationTitle
            }
        }
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            navigationTitle = navigationItem.title ?? ""
            navigationItem.title = ""
        }
    }
    
  2. If you want to use your custom icon for back button, you should create UIBarButtonItem with your image, add target, selector, handle action of the button. Sample BaseViewController class below:

    class BaseViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            let backImage = UIImage(named: "arrow_left")
            navigationItem.hidesBackButton = true
            guard let navigationController = navigationController else {
                return
            }
            if navigationController.viewControllers.count > 1 {
                // we have to set back button only when we have at least 1 controller to go back
                navigationItem.leftBarButtonItem = UIBarButtonItem(image: backImage, style: .plain, target: self, action: #selector(backBarButtonAction(sender:)))
            }
         }
    
         // MARK: Actions
         func backBarButtonAction(sender: UIBarButtonItem) {
             navigationController?.popViewController(animated: true)
         }
    }
    

Upvotes: 1

Krunal
Krunal

Reputation: 79646

There are three ways to do what you want.

  1. I recommend: Create your own Navigation Class by extending and UINavigationController and override backbuttonItem (UIBarButtonItem) property to customise it according to your requirement. And use the same Navigation Controller class in your project.

  2. Create a custom backBarButton by extending UIBarButtonItem and manually set the same as a back button of default Navigation Controller class, in all view controller.

  3. Hide default navigation bar from root controller and create your own navigation bar using UIView and UIButton in all view controllers. (I always use this choice, that makes customization of navigation bar very easy for me. And I can set my view according to my requirement)

Upvotes: 2

Devang Tandel
Devang Tandel

Reputation: 3008

Here is how you can add Custom button for your navigation bar

 let btnleft : UIButton = UIButton(frame: CGRect(x:0, y:0, width:35, height:35))
 btnleft.contentMode = .center
 btnleft.setImage(Set_Local_Image("arrow_left"), for: .normal)
 btnleft.addTarget(self, action: #selector(YOUR_ACTION), for: .touchDown)

let backBarButon: UIBarButtonItem = UIBarButtonItem(customView: btnleft)
self.navigationItem.setLeftBarButtonItems([menuBarButon], animated:false)

instead of "arrow_left" You can use any image you want

For Default back action you can create function(YOUR_ACTION) and use in selector of back button

navController.popViewController(animated: true)

Upvotes: 2

cole
cole

Reputation: 3357

UINavigationBar.appearance().setBackgroundImage(UIImage(), for: 
UIBarPosition.any, barMetrics: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().barTintColor = UIColor.main
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().clipsToBounds = false
UINavigationBar.appearance().backgroundColor = UIColor.main
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : 
 (UIFont(name: "Helvetica", size: 18))!, NSForegroundColorAttributeName: 
  UIColor.white]

Try this code and make changes accordingly to set image, color and other properties

Upvotes: 0

Related Questions