Swift: How do I create a custom UINavigationBar and add a custom back button? - ios

I am trying to create a custom navigationBar.
I am hiding the original navigationBar in viewWillAppear like so:
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.isNavigationBarHidden = true
}
I am subclassing UINavigationBar like so:
let navBar: UINavigationBar = {
let view = UINavigationBar()
view.backgroundColor = .clear
view.isTranslucent = true
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
In viewDidLoad I am calling setupNavBar():
func setupNavBar() {
view.addSubview(navBar)
self.navBar.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 80)
let backButton = UIBarButtonItem(image: UIImage(named:"backThick"), style: .plain, target: self, action: #selector(popControllerOffStack))
}
The problem is that backButton is added to the original navigationBar that is being hidden. This makes me think I am incorrectly creating the navigationBar. How do I add the button to navBar?
Updated Code (still not working):
class CustomNavBar: UINavigationBar {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .red
}
}
// In the viewController
let navBar = CustomNavBar()
override func viewDidLoad() {
super.viewDidLoad()
setupNavBar()
}
func setupNavBar() {
view.addSubview(navBar)
navBar.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 80)
let backButton = UIBarButtonItem(image: UIImage(named:"backThick"), style: .plain, target: self, action: #selector(popControllerOffStack))
self.navigationItem.leftBarButtonItem = backButton
}
The button is being added to the original navigationBar.

You are not subclassing UINavigationBar. Rather, you are creating a new instance of UINavigationBar and modifying its properties inside a computed variable. This means each time you access navBar, you are initializing a new UINavigationBar object.
To create a subclass:
class MyCustomNavigationBar: UINavigationBar {
// Set properties in here after initialization
}
Once you have a proper subclass created, You can initialize an instance like so:
var navBar = MyCustomNavigationBar()
Finally, add your button to the navigation bar:
let backButton = UIBarButtonItem(image: UIImage(named:"backThick"), style: .plain, target: self, action: #selector(popControllerOffStack))
// Assuming 'self' is an instance of UINavigationController()
self.navigationItem.leftBarButtonItem = backButton
See the official Swift Programming Language Guide on Inheritance.

Swift 3.0
You can set custom Back button as like below
self.navigationItem.hidesBackButton = true
let backButton = UIBarButtonItem(image: UIImage(named: "image_name"), style: .plain, target: self, action: #selector(Class.methodName))
backButton.tintColor = UIColor.white
self.navigationItem.leftBarButtonItem = backButton

Also you can try below code:
let btnLeftMenu: UIButton = UIButton()
btnLeftMenu.setImage(UIImage(named: "image_name"), for:UIControlState())
btnLeftMenu.addTarget(self, action: #selector(moveImage), for:UIControlEvents.touchUpInside)
btnLeftMenu.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
let barButton = UIBarButtonItem(customView: btnLeftMenu)
self.navigationItem.leftBarButtonItem = barButton*

Related

How to replace back button in Material in Swift

I want to change behavior of back button and I replace back button of Material with new bar button like bellow:
let backButton: UIButton = {
let btn = UIButton()
btn.setImage(UIImage(named: "prev"), for: .normal)
btn.frame = CGRect(x: 0, y: 0, width: 33/2, height: 27/2)
return btn
}()
In viewDidLoad function:
override func viewDidLoad() {
super.viewDidLoad()
backButton.action = { [weak self] in self?.showAlert() }
let barButton = UIBarButtonItem(customView: backButton)
navigationItem.backButton.isHidden = true
navigationItem.leftBarButtonItems = [barButton]
}
But I can not click to new back button because it was coverred by UINavigationBarBackIndicatorView.
How can I replace back button with Material. I want to keep Material library because in other features of project I need Material.
Thanks in advance for help.
Do this in your viewDidLoad() method :
self.navigationItem.backBarButtonItem.hidden = YES
let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(YourViewController.back(sender:)))
self.navigationItem.leftBarButtonItem = newBackButton
self.navigationItem.leftBarButtonItem?.image = UIImage(named : "prev")
self.navigationItem.leftBarButtonItem?.accessibilityFrame = CGRect(x: 0, y: 0, width: 33/2, height: 27/2)
Then define a function named back in your view controller,this function will perform the desired action for your new back button
func back(sender: UIBarButtonItem) {
// Perform your custom action
}
Note No need to define a separate button variable
**If self.navigationItem.backBarButtonItem.hidden = YES doesnt works then replace it with self.navigationItem.backBarButtonItem = nil; **
Using backButton.isHidden with leftViews containing the new custom IconButtom works for me, I'm using Material 2.17.0.
func setNavigation() {
let backButton = IconButton(image: Icon.cm.arrowBack)
backButton.addTarget(self, action: #selector(onBackTapped), for: .touchUpInside)
navigationItem.leftViews = [backButton]
navigationItem.backButton.isHidden = true
}

BarButtonItem EdgeInsets doesn't work

I'm trying to add a padding to the right of a navigationBar rightBarButtonItems in between the buttons but it's now working.
Here's the button creation code with the given inset:
lazy var previewBarButtonItem: UIBarButtonItem = {
let buttonItem = UIBarButtonItem(title: "Preview", style: .plain, target: self, action: #selector(handlePreview))
buttonItem.tintColor = UIColor.black
buttonItem.setTitleTextAttributes([NSFontAttributeName: UIFont.systemFont(ofSize: 14)], for: .normal)
buttonItem.imageInsets = UIEdgeInsetsMake(0, -15, 0, 15)
return buttonItem
}()
override func viewDidLoad() {
super.viewDidLoad()
setupRightNavItems()
}
fileprivate func setupRightNavItems () {
navigationItem.rightBarButtonItems = [submitBarButtonItem, previewBarButtonItem]
}
Can you give a hint on why this isn't working?
Thanks
I managed to fix this issue, just added a fixedSpace in-between the bar button items as follows:
1) remove any EdgeInsets
2) add the following fixed space:
fileprivate func setupRightNavItems () {
let spacing = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
spacing.width = 25 //change to your desired space width
navigationItem.rightBarButtonItems = [submitBarButtonItem, spacing, previewBarButtonItem]
}

Navigation Title background image not working

This my simulator screen shot
import UIKit
class NewsTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
addCustomNavigationBarToView()
}
// This is my custom navigation bar Function
func addCustomNavigationBarToView(){
// Here i create a navigationBar variable
let navigationBar = UINavigationBar(frame: CGRect(x:0, y:0, width: self.view.frame.size.width, height: 100))
let navBackgroundImage:UIImage! = UIImage(named: "BarBa.jpg") self.navigationController?.navigationBar.setBackgroundImage(navBackgroundImage,for: .default)
//i was created navigation item variable and setup an image
let navigationItem = UINavigationItem()
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 220, height: 90 ))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "logo.png")
imageView.image = image
navigationItem.titleView = imageView
// Create left and right button for navigation item
let leftButton = UIBarButtonItem(title: "Save", style: UIBarButtonItemStyle.plain, target: self, action: Selector(("saveButtonClicked:")))
navigationItem.leftBarButtonItem = leftButton
//tapping the menu button work
// Assign the navigation item to the navigation bar
navigationBar.items = [navigationItem]
self.view.addSubview(navigationBar)
}
}
In addCustomNavigationBarToView function you have written wrong code:
Your TableViewController don't have any NavigationBar but you are currently setting background Image to self.navigationController.navigationBar :
{ self.navigationController?.navigationBar.setBackgroundImage(navBackgroundImage,for: .default)
}
You need to change your code to:
{
navigationBar.setBackgroundImage(navBackgroundImage,for: .default)
}

Adding multiple custom bar buttons to custom nav bar

I need to add two bar button items to each end of my custom navigation bar in Swift. I'm using the following method, and although I get no errors, nothing at all is appearing. I'm using my own custom icons, which do appear when I add them using interface builder. Obviously, I can only add one to each end that way.
#IBOutlet weak var navBar: UINavigationBar!
override func viewDidLoad() {
var iconOne = UIImage(named: "iconOne")
var iconTwo = UIImage(named: "iconTwo")
var buttonOne:UIBarButtonItem = UIBarButtonItem(image: iconOne, style: UIBarButtonItemStyle.Plain, target: self, action: nil)
var buttonTwo:UIBarButtonItem = UIBarButtonItem(image: iconTwo, style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.navBar.setItems([buttonOne,buttonTwo], animated: true)
}
This is implemented in a view controller that's embedded in a navigation controller. I'd be able to use self.navigationItem.setRightBarButtonItems([buttonOne, buttonTwo], animated: true) if I weren't using a custom nav bar. What's the workaround?
This code works for me:
#IBOutlet weak var navBar: UINavigationBar!
#IBOutlet weak var navBarItem: UINavigationItem!
func displayTextInNavBar(text: String) {
let labelWidth: CGFloat = navBar.frame.width / 6
let frame = CGRect(x: 0, y: 0, width: labelWidth, height: navBar.frame.height)
let label = UILabel(frame: frame)
label.textAlignment = .Right
label.textColor = UIColor(red: 0/255, green: 127/255, blue: 0/255, alpha: 1)
label.font = UIFont(name: "Bradley Hand", size: 20)
label.text = text
let navBarButtonItem = UIBarButtonItem(customView: label)
navBarItem.rightBarButtonItem = navBarButtonItem
}
The above puts a label on the right side of the navBar. If you want an actual button that is clickable, do this instead:
let navBarButtonItem = UIBarButtonItem(title: text, style: .Plain, target: self, action: nil)
If you want that button to actually do something when clicked, then instead of nil specify some function.
My solution to do it:
var barButton : UIBarButtonItem?
override func viewDidLoad() {
self.barButton = UIBarButtonItem(title: "Options", style: .plain, target: self, action: nil))
self.navigationItem.rightBarButtonItems = [barButton] as? [UIBarButtonItem]
}
UIBarButtonItem can be created with an custom view
create a view
add UIButtons to it
layout it
create a UIBarButtonItem with custom view
add it to the navigation bar

iOS rightBarButtonItem on UINavigationController in swift

I'm trying to put a rightBarButtonItem on a second view controller of an UINavigationViewController stack.
I'm creating and setting the button in viewDidLoad of the view controller that I want to show. My actual code looks like this:
override func viewDidLoad() {
super.viewDidLoad()
menu_button_ = UIBarButtonItem(image: UIImage(named: "menu"),
style: UIBarButtonItemStyle.Plain ,
target: self, action: "OnMenuClicked:")
self.navigationController!.navigationItem.rightBarButtonItem = menu_button_
}
What am I missing? The button doesn't appear.
You should set the menu_button_ as the rightBarButtonItem of your viewController rather than the navigationController.
Try
self.navigationItem.rightBarButtonItem = menu_button_
instead of
self.navigationController!.navigationItem.rightBarButtonItem = menu_button_
try with following code. it works for me.
let homeButton : UIBarButtonItem = UIBarButtonItem(title: "LeftButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
let logButton : UIBarButtonItem = UIBarButtonItem(title: "RigthButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
self.navigationItem.leftBarButtonItem = homeButton
self.navigationItem.rightBarButtonItem = logButton
And if you want to settle out custom image then please check with apple guidelines on below link.
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/BarIcons.html#//apple_ref/doc/uid/TP40006556-CH21-SW1
In Swift 5
//For righter button item
let rightBtn = UIBarButtonItem(image: UIImage(named: "rightmenu"), style: .plain, target: self, action: #selector(onClickMethod))//Change your function name and image name here
self.navigationItem.rightBarButtonItem = rightBtn
//self.navigationItem.rightBarButtonItem = [rightBtn, anotherBtn] //If you want to add more buttons add like this
//This is your function
#objc func onClickMethod() {
print("Left bar button item")
}
Create an extension of UINavigationItem like -
extension UINavigationItem {
func addSettingButtonOnRight(){
let button = UIButton(type: .custom)
button.setTitle("setting", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 15.0)
button.layer.cornerRadius = 5
button.backgroundColor = .gray
button.frame = CGRect(x: 0, y: 0, width: 100, height: 25)
button.addTarget(self, action: #selector(gotSettingPage), for: UIControlEvents.touchUpInside)
let barButton = UIBarButtonItem(customView: button)
self.rightBarButtonItem = barButton
}
#objc func gotSettingPage(){
}
}
And call it from viewDidLoad() like -
self.navigationItem.addSettingButtonOnRight()

Resources