Hi,
I'm trying to figure out how to change the back button to a custom image on all ViewControllers. I read though a few questions regarding to this solution, but it was mostly outdated.
I want to change < Back to a stock image I have
I was able to disable to hide the back but that's not my goal my goal is to change the default image to a custom one, I added the custom image to the images.xcassets and that didn't work also I tried to set the System Item to Custom and under Bar Item I selected my image which is image.png, but still didn't work, can someone help me approach this solution? Thanks.
override func viewDidLoad() {
let image: UIImage = UIImage(named: "images")!
self.navigationController?.navigationItem.backBarButtonItem?.image = image
}
override func viewDidAppear(animated: Bool) {
// let backButton = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: navigationController, action: nil)
// navigationItem.leftBarButtonItem = backButton
self.navigationItem.setHidesBackButton(false, animated: false)
}
Instead of doing that you can create your own custom button and assign it to leftBarButtonItem. Try this out
var backBtn = UIBarButtonItem()
let image: UIImage = UIImage(named: "images")!
backBtn.image = image
//set other properties for your button
//set traget and action
self.navigationItem.leftBarButtonItem = backBtn
You can just pop the current view controller in action of the back button.
You can add this in AppDelegate
UIBarButtonItem.appearance().setBackButtonBackgroundImage(UIImage(named: name), forState: .Normal, barMetrics: .Default)
This will set back button through out the app
Related
Since left button is a different thing, and like back bar button it doesn't help in navigation to the last page it is coming from, I am not interested in using it. However I want to edit the back button such that it removes default the back indicator image (arrow) and have text value- "Cancel" and it navigates it to the last page it is coming from.
I have tried few things. Some of them reflects in all of the pages in the app unfortunately and not just on the current page. Some don't work at all (needless to say)
self.navigationController?.navigationBar.backIndicatorImage = UIImage()
Your question has two parts:
Changing the text of the back item
Changing the back indicator image
Changing the Title
The back item of a view controller actually belongs to the previous view controller. You can change this in the previous controller's code (ie. the controller you are coming from) with the following code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let backItem = UIBarButtonItem()
backItem.title = "Cancel" // Change to whatever you want
backItem.tintColor = UIColor.red // The color of the text can be changed too if you want
navigationItem.backBarButtonItem = backItem // Will show in the next view controller being pushed
}
Changing the Back Indicator Image
Changing the title as seen above only changes the text ("cancel" in your case), but does not actually change the indicator icon or image. To do this, go into the class for the view controller you are trying to change.
override func viewDidLoad() {
super.viewDidLoad()
// "image" is file you want
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "image")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "image")
}
Create a base navigation controller, you can edit image, text color and font in this way.
class BaseNavigationController: UINavigationController {
init() {
super.init(nibName: nil, bundle: nil)
self.navigationBar.titleTextAttributes = [
NSAttributedStringKey.foregroundColor: color,
NSAttributedStringKey.font: font
]
self.navigationBar.barTintColor = color
if #available(iOS 11, *) {
self.navigationBar.backIndicatorImage = image
self.navigationBar.backIndicatorTransitionMaskImage = image
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
try this:
override func viewDidLoad() {
super.viewDidLoad()
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancel))
navigationItem.leftBarButtonItem = cancelButton
}
#objc func cancel(){
navigationController?.popViewController(animated: true)
}
you can also initialize the UIBarButtonItem with a custom image, and you can also do this in the storyboard you don't have to necessarily use code.
My app requires me to add multiple buttons in my navigation bar.
Here is an image of what my nav bar looks like
How do i achieve this type of design?
You can configure your view controller's navigationItem in various ways to achieve this design.
Left side
To allow additional buttons next to the system "back button" on the left:
navigationItem.leftItemsSupplementBackButton = true
This allows you to add a left bar button item for the circular image:
navigationItem.setLeftBarButtonItem(imageItem, animated: trueOrFalse)
imageItem would be a UIBarButtonItem initialized with a customView or image, as discussed in some of the other answers here.
For the back button itself, to achieve a simple "<" without showing the title of the previous view or showing "< Back", you can open the storyboard and set the Back Button text of the previous view controller to a single space, as described in this post.
Title area
For the title area, as discussed in the other answers:
navigationItem.titleView = (a custom view)
Right side
For the right side, you can add multiple buttons:
navigationItem.setRightBarButtonItems([button1, button2, button3, button4], animated: trueOrFalse)
Here, button1, button2, button3, and button4 are each UIBarButtonItems. You would likely initialize these buttons with images.
Looks like you also will want to set the tintColor of the navigation bar to black, so that the bar buttons are rendered in black:
navigationController?.navigationBar.tintColor = .black
All of this code would be done in the view controller, usually in viewDidLoad, unless you need to dynamically change which buttons are shown as the content of your view controller changes.
Try this:
let callImage = UIImage(named: "call")!
let videoImage = UIImage(named: "video")!
let searchImage = UIImage(named: "search")!
let callButton = UIBarButtonItem(image: callImage, style: .plain, target: self, action: #selector(didTapCallButton))
let videoButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapVideoButton))
let searchButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapSearchButton))
navigationItem.rightBarButtonItems = [callButton, videoButton, searchButton]
Selector methods
func didTapCallButton(sender: AnyObject){
...
}
func didTapVideoButton(sender: AnyObject){
...
}
func didTapSearchButton(sender: AnyObject){
...
}
You can create your own view and put down your Images, Labels, etc...
After that, you write:
self.navigationItem.titleView = yourView
UINavigationItem has a property called rightBarButtonItems, this expects an array of UIBarButtonItem which would in your case be each of your buttons.
You can use the initialiser on UIBarButtonItem to specify the image and style:
init(image: UIImage?, style: UIBarButtonItemStyle, target: Any?, action: Selector?)
Initializes a new item using the specified image and other properties.
On your view controller you can access the navigation item through the accessor navigationItem, if you embed your view controller inside a UINavigationController you will need to access the navigationItem on that instance and not the view controller.
You can Add UIView in navigation bar so that you can add multiple buttons in that view.
This is the back icon and back text now:
But if I want my navigation back like this:
I have tried to set the back to my want icon image:
But it useless.
You can hide back button text in many ways.Try this simple approach.
Step1: Goto your mainstoryBoard and click navigationBar.
Step 2: Goto Attributes Inspector under Navigation Item add a BLANK SPACE in Back Button
Step 3: If you want to change backButton text method is pretty much the same.
Update 1: If you want to use an image as a back button check this link
Update 2:
Method 2: Using custom image as a back button.
Paste below code into your detailVC and set image for your back Button.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
title = "Detail VC"
let customButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(backButtonTapped)) //
self.navigationItem.leftBarButtonItem = customButton
}
func backButtonTapped() {
_ = navigationController?.popToRootViewController(animated: true)
}
I am setting back button image in assets catalogue with the 32pixel size.I am not sure about the asset image size.Check with apple doc about the size class.
Output:
Create a new UIBarButton and add it the navigationItem.leftBarButton.
let backButton = UIBarButtonItem(image: UIImage(named:"yourImage"), style: .plain, target: self, action: #selector(yourBackMethod(sender:))
navigationItem.leftBarButtonItem = = backButton
#objc internal func yourBackMethod(sender: AnyObject) {
navigationController.popViewController()
}
Hope this helps.
I have this below code that changes the back button image on next screen.
I have 30 screens in my app and i want back button to be same across all 30 screens. Is it possible that I don't copy paste this code on all 30 screens and just write it once and rather reuse it across 30 screens.
Also, the code attached with back button should work fine on all screens when i reuse it
I am using iOS 8 and Xcode 6.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let backButtonImage: UIImage = UIImage(named: "back")!
var backBarItem: UIBarButtonItem = UIBarButtonItem(image: backButtonImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
segue.destinationViewController.navigationItem.leftBarButtonItem = backBarItem;
}
func method() {
self.navigationController?.popViewControllerAnimated(true)
}
You can change it globally
UINavigationBar.appearance().backIndicatorImage = UIImage(named: "custom-back")
UINavigationBar.appearance().backIndicatorTransitionMaskImage = UIImage(named: "custom-back")
Or per navigation controller.
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.backIndicatorImage = UIImage(named: "custom-back")
navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "custom-back")
}
Full detail here https://sarunw.com/posts/how-to-change-back-button-image/
To general change the appearance of UI-Elements in iOS look at UIAppearance. This way you can set it once and it will be everywhere in your app.
I would recommend setting it in the AppDelegate application:didFinishLaunchingWithOptions:.
Try this:
let backImg: UIImage = UIImage(named: "back")!
UIBarButtonItem.appearance().setBackButtonBackgroundImage(backImg, forState: .Normal, barMetrics: .Default)
I only have one navigation Controller in my app, so this may or may not be helpful. But, I created a subclass of UINavigationController. Then in this subclass, I override the pushViewController method:
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
let pushingVC = viewControllers[viewControllers.count - 1]
let backItem = UIBarButtonItem()
backItem.title = ""
pushingVC.navigationItem.backBarButtonItem = backItem
super.pushViewController(viewController, animated: animated)
}
This, makes it so every time a viewController is pushed, from my customNavigationController, it uses the custom back button for every view. You have to make sure you change your UINavigationControllers type to your custom Subclass. But, this works for me in Swift 3.0.
You could use appearance()
Swift
let backImage = UIImage(named: "back")
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor:
UIColor.white], for: .normal)
UIBarButtonItem.appearance().tintColor = UIColor.green
I'm not quite sure what you wanted, so I'll answer most of what I think you could want for your sake and anyone looking at this in the future.
First: You want a back button similar to those on default apple apps. To do so, you need to a) get a reference to the destination scene and it's view controller. I will assume you have done so and set it equal to controller for future reference. b) You need to set the left bar button item. Set it with:
controller.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Insert Title Here!!", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
Place all of this in prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) (you will also find the destination scene with this, likely with segue.destinationViewController
Second: You want to use an image named "Back" for all items. If so, repeat step a) above, and insert this handy bit of code:
UIBarButtonItem(image: "Back", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
I also know you want to not have to copy it, but it's not as if this is that computer intensive anyways and it's probably simplest.
Third: You're smart and don't hate advances in programming so you want to use a storyboard. If so, simply drag in a Navigation Bar from the object menu, add a navigation item, and copy it to all of your scenes. If your scenes are linked to custom classes, then super happy fun time good news, you can simply link the navigation item to your custom class through an IBAction and use that function to do all the fancy coding your heart could ever desire.
Fourth: You really, really don't want to copy anything even if it's not that hard. If so, you can subclass a UIViewController with your own custom class, add the code I mentioned above, and then subclass all your future UIView classes as this. To be honest, I'm not entirely sure this would work and it seems unnecessarily laborious, but it's up to you.
I'm a bit tired right now so sorry for all the things I'm finding funny, but I hope I helped, and please tell me if I missed your point entirely and I can try and think of a solution.
View hierarchy:
UINavigationController
->UITableViewController(1)
->UITableViewController(2)
->UIViewController(3)
In 1 and 2 I have this code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
self.navigationItem.backBarButtonItem?.title = ""
}
It should override the back button title of the next view controller pushed on the current view controller. It works from 1 -> 2. But it does not work for 2 -> 3. In 3 the back button title has a title, the name of the previous UITableViewController.
Any ideas whats wrong? I am using swift, xcode6.1 and iOS8.1
You could init a new back button with no title. Just put this in the viewDidLoad() of each view controller.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
--
I am going to extend this answer with my experience. So I managed to remove the title of the back button to display just the back arrow. In storyboard you have to select the navigation item that displays the title inside the navigation bar of the previous view controller. There is a property called Back Button. Just enter a space and save. It will remove the back button title.
Update
UIBarButtonItemStyle.Bordered was deprecated in iOS 8.0. Use UIBarButtonItemStyle.Plain instead.
thanks,
if you want using customer back button image, you can use this
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: “backImage”)
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: “ backImage”)
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: “”, style: UIBarButtonItemStyle.Plain, target: nil, action: nil)