Related
I am trying to set an Image for bar button Item for that I have an image like:
with resolution 30 * 30 but while I assign this Image to Bar button Its looks like:
I have assigned image this way :
and If I try this way like making an IBOutlet for the button and set Image programatically form this question and code for that is:
// Outlet for bar button
#IBOutlet weak var fbButton: UIBarButtonItem!
// Set Image for bar button
var backImg: UIImage = UIImage(named: "fb.png")!
fbButton.setBackgroundImage(backImg, forState: .Normal, barMetrics: .Default)
but nothing happend with this,
Can anybody tell me what I am doing wrong?
or which is the batter way to do this?
I have achieved that programatically with this code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//create a new button
let button: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
//set image for button
button.setImage(UIImage(named: "fb.png"), forState: UIControlState.Normal)
//add function for button
button.addTarget(self, action: "fbButtonPressed", forControlEvents: UIControlEvents.TouchUpInside)
//set frame
button.frame = CGRectMake(0, 0, 53, 31)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
//This method will call when you press button.
func fbButtonPressed() {
println("Share to fb")
}
}
And result will be:
Same way you can set button for left side too this way:
self.navigationItem.leftBarButtonItem = barButton
And result will be:
And if you want same transaction as navigation controller have when you go back with default back button then you can achieve that with custom back button with this code:
func backButtonPressed(sender:UIButton) {
navigationController?.popViewControllerAnimated(true)
}
For swift 3.0:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//create a new button
let button = UIButton.init(type: .custom)
//set image for button
button.setImage(UIImage(named: "fb.png"), for: UIControlState.normal)
//add function for button
button.addTarget(self, action: #selector(ViewController.fbButtonPressed), for: UIControlEvents.touchUpInside)
//set frame
button.frame = CGRect(x: 0, y: 0, width: 53, height: 51)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
//This method will call when you press button.
func fbButtonPressed() {
print("Share to fb")
}
}
For swift 4.0:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//create a new button
let button = UIButton(type: .custom)
//set image for button
button.setImage(UIImage(named: "fb.png"), for: .normal)
//add function for button
button.addTarget(self, action: #selector(fbButtonPressed), for: .touchUpInside)
//set frame
button.frame = CGRect(x: 0, y: 0, width: 53, height: 51)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
//This method will call when you press button.
#objc func fbButtonPressed() {
print("Share to fb")
}
}
An easy solution may be the following
barButtonItem.image = UIImage(named: "image")
then go to your Assets.xcassets select the image and go to the Attribute Inspector and select "Original Image" in Reder as option.
Similar to the accepted solution, but you can replace the
let button: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
with
let button = UIButton()
Here is the full solution, enjoy: (it's just a bit cleaner than the accepted solution)
let button = UIButton()
button.frame = CGRectMake(0, 0, 51, 31) //won't work if you don't set frame
button.setImage(UIImage(named: "fb"), forState: .Normal)
button.addTarget(self, action: Selector("fbButtonPressed"), forControlEvents: .TouchUpInside)
let barButton = UIBarButtonItem()
barButton.customView = button
self.navigationItem.rightBarButtonItem = barButton
Here's a simple extension on UIBarButtonItem:
extension UIBarButtonItem {
class func itemWith(colorfulImage: UIImage?, target: AnyObject, action: Selector) -> UIBarButtonItem {
let button = UIButton(type: .custom)
button.setImage(colorfulImage, for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 44.0, height: 44.0)
button.addTarget(target, action: action, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
return barButtonItem
}
}
Only two Lines of code required for this
Swift 3.0
let closeButtonImage = UIImage(named: "ic_close_white")
navigationItem.rightBarButtonItem = UIBarButtonItem(image: closeButtonImage, style: .plain, target: self, action: #selector(ResetPasswordViewController.barButtonDidTap(_:)))
func barButtonDidTap(_ sender: UIBarButtonItem)
{
}
I am using latest swift (2.1) and the answer (Dharmesh Kheni and jungledev) does not work for me. The image color was off (when setting in IB, it was blue and when setting directly in UIButton, it was black). It turns out I could create the same bar item with the following code:
let barButton = UIBarButtonItem(image: UIImage(named: "menu"), landscapeImagePhone: nil, style: .Done, target: self, action: #selector(revealBackClicked))
self.navigationItem.leftBarButtonItem = barButton
You can use this code for multiple bar button with custom image:
self.navigationItem.leftBarButtonItem = nil
let button = UIButton(type: .custom)
button.setImage(UIImage (named: "ChatTab"), for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
let button2 = UIButton(type: .custom)
button2.setImage(UIImage (named: "ActivityTab"), for: .normal)
button2.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem2 = UIBarButtonItem(customView: button2)
self.navigationItem.rightBarButtonItems = [barButtonItem, barButtonItem2]
Result will be this:
Initialize barbuttonItem like following:
let pauseButton = UIBarButtonItem(image: UIImage(named: "big"),
style: .plain,
target: self,
action: #selector(PlaybackViewController.pause))
Your problem is because of the way the icon has been made - it doesn't conform to Apple's custom tab bar icon specs:
To design a custom bar icon, follow these guidelines:
Use pure white with appropriate alpha transparency.
Don’t include a drop shadow.
Use antialiasing.
(From the guidelines.)
Something that would be possible looks like this. You can find such icons on most free tab bar icon sites.
Swift 4.
#IBOutlet weak var settingBarBtn: UIBarButtonItem! {
didSet {
let imageSetting = UIImageView(image: UIImage(named: "settings"))
imageSetting.image = imageSetting.image!.withRenderingMode(.alwaysOriginal)
imageSetting.tintColor = UIColor.clear
settingBarBtn.image = imageSetting.image
}
}
SwiftUI
.navigationBarItems modifier takes any view you want:
struct ContentView: View {
var body: some View {
NavigationView {
Text("SwiftUI")
.navigationBarItems(leading:
HStack {
Image(systemName: "trash")
Text("Trash")
}
)
}
}
}
.navigationBarItems(trailing: Image(systemName: "trash") )
.navigationBarItems(leading: Image(systemName: "trash.fill"),
trailing: Image(systemName: "trash")
)
You can use a button for each if you need an action for each of them.
Swift 5+. Smooth solution to add ideal image as you desired dynamic Solution
func rightBarButtonItem(iconNameButton: String, selector: Selector) {
let button = UIButton()
button.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
button.setImage(UIImage(named: iconNameButton), for: .normal)
button.addTarget(self, action: selector, for: .touchUpInside)
button.imageView?.contentMode = .scaleAspectFit
let buttonBarButton = UIBarButtonItem(customView: UIView(frame: CGRect(x: 0, y: 0, width: 25, height: 25)))
buttonBarButton.customView?.addSubview(button)
buttonBarButton.customView?.frame = button.frame
self.navigationItem.rightBarButtonItem = buttonBarButton
}
Just choose Original image option when adding an image to assets in Xcode
If your UIBarButtonItem is already allocated like in a storyboard.
(printBtn)
let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
btn.setImage(UIImage(named: Constants.ImageName.print)?.withRenderingMode(.alwaysTemplate), for: .normal)
btn.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handlePrintPress(tapGesture:))))
printBtn.customView = btn
If you have set up your UIBarButtonItem with an image in the storyboard, one small hack to change the renderingMode is to add the following code to your viewDidLoad(). This way you don't have to resort to adding the entire button and image in code.
if let navButton = self.navigationItem.leftBarButtonItem, let buttonImage = navButton.image {
navButton.image = buttonImage.withRenderingMode(.alwaysOriginal)
}
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Left",
style: .plain,target: self, action: #selector(rightbarButtonAction))
navigationItem.rightBarButtonItem?.image = UIImage(named: "Notification Bell")
I am trying to change the size of some icons in my navBar, but I am a little confused as to how to do this? My code so far is:
func setUpNavBarButtons() {
let moreButton = UIBarButtonItem (image: UIImage(named:"ic_more_vert_3")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleMore))
navigationItem.rightBarButtonItems = [moreButton]
let refreshButton = UIBarButtonItem (image: UIImage(named:"ic_refresh")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(refreshDataButton))
navigationItem.leftBarButtonItems = [refreshButton]
}
any help?
This is how I did it
iOS 10 and below
func setUpMenuButton(){
let menuBtn = UIButton(type: .custom)
menuBtn.frame = CGRect(x: 0.0, y: 0.0, width: 20, height: 20)
menuBtn.setImage(UIImage(named:"menuIcon"), for: .normal)
menuBtn.addTarget(self, action: #selector(vc.onMenuButtonPressed(_:)), for: UIControlEvents.touchUpInside)
let menuBarItem = UIBarButtonItem(customView: menuBtn)
self.navigationItem.leftBarButtonItem = menuBarItem
}
iOS 11 - Navigation bar come up with Autolayout so frame setting may not work
func setUpMenuButton(){
let menuBtn = UIButton(type: .custom)
menuBtn.frame = CGRect(x: 0.0, y: 0.0, width: 20, height: 20)
menuBtn.setImage(UIImage(named:"menuIcon"), for: .normal)
menuBtn.addTarget(self, action: #selector(vc.onMenuButtonPressed(_:)), for: UIControlEvents.touchUpInside)
let menuBarItem = UIBarButtonItem(customView: menuBtn)
let currWidth = menuBarItem.customView?.widthAnchor.constraint(equalToConstant: 24)
currWidth?.isActive = true
let currHeight = menuBarItem.customView?.heightAnchor.constraint(equalToConstant: 24)
currHeight?.isActive = true
self.navigationItem.leftBarButtonItem = menuBarItem
}
Extension for Swift 4.2
Just a different way of implementation the answer provided by anoop4real
However using button type .system allows the global tint to be applied to your icon
Usage:
navigationItem.leftBarButtonItem = UIBarButtonItem.menuButton(self, action: #selector(presentSettings), imageName: "settings")
Implementation:
extension UIBarButtonItem {
static func menuButton(_ target: Any?, action: Selector, imageName: String) -> UIBarButtonItem {
let button = UIButton(type: .system)
button.setImage(UIImage(named: imageName), for: .normal)
button.addTarget(target, action: action, for: .touchUpInside)
let menuBarItem = UIBarButtonItem(customView: button)
menuBarItem.customView?.translatesAutoresizingMaskIntoConstraints = false
menuBarItem.customView?.heightAnchor.constraint(equalToConstant: 24).isActive = true
menuBarItem.customView?.widthAnchor.constraint(equalToConstant: 24).isActive = true
return menuBarItem
}
}
You can configure the frame of you button like below:
let icon = UIImage(named: "imageName")
let iconSize = CGRect(origin: CGPoint.zero, size: CGSize(width: 50, height: 50))
let iconButton = UIButton(frame: iconSize)
iconButton.setBackgroundImage(icon, for: .normal)
let barButton = UIBarButtonItem(customView: iconButton)
iconButton.addTarget(self, action: #selector(foo), for: .touchUpInside)
navigationItem.leftBarButtonItem = barButton
#DogCoffee answer is a great and creative way to solve the problem. May I suggest some slightly mods in order to take into account size and tintColor
extension UIBarButtonItem {
static func menuButton(_ target: Any?,
action: Selector,
imageName: String,
size:CGSize = CGSize(width: 32, height: 32),
tintColor:UIColor?) -> UIBarButtonItem
{
let button = UIButton(type: .system)
button.tintColor = tintColor
button.setImage(UIImage(named: imageName), for: .normal)
button.addTarget(target, action: action, for: .touchUpInside)
let menuBarItem = UIBarButtonItem(customView: button)
menuBarItem.customView?.translatesAutoresizingMaskIntoConstraints = false
menuBarItem.customView?.heightAnchor.constraint(equalToConstant: size.height).isActive = true
menuBarItem.customView?.widthAnchor.constraint(equalToConstant: size.width).isActive = true
return menuBarItem
}
}
In the end I did it like this and it worked:
let moreButton = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
moreButton.setBackgroundImage(UIImage(named: "ic_more_vert_3"), for: .normal)
moreButton.addTarget(self, action: #selector(TableViewController.handleMore), for: .touchUpInside)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: moreButton)
Answer from: Change width of a UIBarButtonItem in a UINavigationBar in swift
If you are using SF symbol image, which is available from iOS 13, you could set the SF symbol image configuration.
let config = UIImage.SymbolConfiguration(pointSize: 30, weight: .light, scale: .default)
let image = UIImage(systemName: "plus.circle", withConfiguration: config)
Swift 5 extension using button closure, expanding on #valvoline 's answer.
As you can appreciate instead of using target and selector Button allows you to pass a closure.
extension UIBarButtonItem {
static func imageButton(
image: UIImage,
size: CGFloat = 24,
color: UIColor = .systemBackground,
action: #escaping () -> Void
) -> UIBarButtonItem {
// create ui button
let button = UIButton(type: .system)
// assign image
button.setImage(image, for: .normal)
button.tintColor = color
// assign action
button.addAction(.init(handler: { _ in action() }), for: .touchUpInside)
// create menu bar item using custom view
let menuBarItem = UIBarButtonItem(customView: button)
//use auto layout to assign bar button's size
menuBarItem.customView?.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(
[
menuBarItem.customView?.heightAnchor.constraint(equalToConstant: size),
menuBarItem.customView?.widthAnchor.constraint(equalToConstant: size)
].compactMap { $0 }
)
return menuBarItem
}
}
Usage Example:
let item = UIBarButtonItem.imageButton(image: image, color: .systemBlue) {
print("You pushed it!") }
You can configure the bar buttons using this function:
public convenience init(customView: UIView)
And You can init the custom view as You desire.
After that You can access the view if needed via UIBarButtonItem's:
open var customView: UIView?
Hint: Because UIButton is a child class of UIView, You can directly use it too.
I was able to create a UIBarButton item that can go back programmatically using the following code:
func backAction() -> Void {
self.navigationController?.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "backAction")
self.navigationItem.leftBarButtonItem = backButton
}
The problem is that the back button doesn't have the left pointing arrow:
Is there a way to make it look like a regular back button with the arrow like this:
I would also like to know if there is a way to make the button title names as the title of the previous view controller, if that's possible.
Thanks
Below is the code by using UIButton with image you can add it as a customView for UIBarButtonItem
override func viewDidLoad() {
super.viewDidLoad()
var backbutton = UIButton(type: .Custom)
backbutton.setImage(UIImage(named: "BackButton.png"), forState: .Normal) // Image can be downloaded from here below link
backbutton.setTitle("Back", forState: .Normal)
backbutton.setTitleColor(backbutton.tintColor, forState: .Normal) // You can change the TitleColor
backbutton.addTarget(self, action: "backAction", forControlEvents: .TouchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}
func backAction() -> Void {
self.navigationController?.popViewControllerAnimated(true)
}
Download Link
For setting the title of backbutton with the previous view controller title you have to pass the Title as a String while presenting the controller make change to above code as
var titleStrFromPreviousController: String // This value has to be set from previous controller while presenting modal controller
backbutton.setTitle(titleStrFromPreviousController, forState: .Normal)
This may help.
Swift 3
override func viewDidLoad() {
super.viewDidLoad()
addBackButton()
}
func addBackButton() {
let backButton = UIButton(type: .custom)
backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func backAction(_ sender: UIButton) {
let _ = self.navigationController?.popViewController(animated: true)
}
Updated for Swift 4.2 - thanks to sam bing and silentbeep
Made some modifications on some colors and action's selector.
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .blue
self.navigationItem.title = title
self.navigationController?.navigationBar.barTintColor = .white
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: makeBackButton())
}
func makeBackButton() -> UIButton {
let backButtonImage = UIImage(named: "backbutton")?.withRenderingMode(.alwaysTemplate)
let backButton = UIButton(type: .custom)
backButton.setImage(backButtonImage, for: .normal)
backButton.tintColor = .blue
backButton.setTitle(" Back", for: .normal)
backButton.setTitleColor(.blue, for: .normal)
backButton.addTarget(self, action: #selector(self.backButtonPressed), for: .touchUpInside)
return backButton
}
#objc func backButtonPressed() {
dismiss(animated: true, completion: nil)
// navigationController?.popViewController(animated: true)
}
You can do by embedding your view in a navigation controller.
Here is an image showing how to do that:
Hope it helps :D
For future searches, I wanted to add that you can now use the default icon by this code:
override public func viewDidLoad() {
// create chevron image
let config = UIImage.SymbolConfiguration(pointSize: 25.0, weight: .medium, scale: .medium)
let image = UIImage(systemName: "chevron.left", withConfiguration: config)
// create back button
let backButton = UIButton(type: .custom)
backButton.addTarget(self, action: #selector(self.close(_:)), for: .touchUpInside)
backButton.setImage(image, for: .normal)
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func close(_ sender: UIButton) {
self.navigationController?.dismiss(animated: true, completion: nil)
}
The first answer works great however the image is a bit too big so use the preview and scale it down to width:13 and height: 22, also set its rendering mode to .alwaysTemplate and change the UIButton's tint to white, while also adding two spaces before the string : " Back". This will result in something that is quiet similar to the navigation bar back button, the image could be better in terms of size and placement.
Edited code:
func addBackButton() {
let backButtonImage = UIImage(named: "BackButton.png")?.withRenderingMode(.alwaysTemplate)
let backButton = UIButton(type: .custom)
backButton.setImage(backButtonImage, for: .normal)
backButton.tintColor = .white
backButton.setTitle(" Back", for: .normal)
backButton.setTitleColor(.white, for: .normal)
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
I changed one last line of code from selected answer and it works for me.
override func viewDidLoad() {
super.viewDidLoad()
addBackButton()
}
func addBackButton() {
let backButton = UIButton(type: .custom)
backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func backAction(_ sender: UIButton) {
let _ = self.dismiss(animated: true, completion: nil)
}
Swift 5
override func viewDidLoad() {
super.viewDidLoad()
let backbutton = UIButton(type: .custom)
backbutton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backbutton.setTitle("Back", for: .normal)
backbutton.setTitleColor(backbutton.tintColor, for: .normal) // You can change the TitleColor
backbutton.addTarget(self, action: Selector(("backAction")), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}
func backAction() -> Void {
self.navigationController?.popViewController(animated: true)
}
I want to get a button which isn't a bar button item to display the trash bin icon. Does anybody know how to do this programmatically?
Add your action:
func buttonAction(sender:UIButton!)
{
println("Button tapped") // add your button tapped logic here
}
Then inside viewDidLoad:
var image: UIImage = UIImage(named: "Icon")! //Icon = your image name, no need for the extension
let button = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton //UIButton type must be CUSTOM or you will get a plain blue system button
button.frame = CGRectMake(100, 100, 100, 50) // Size and Co-ordinates
button.setImage(image, forState: .Normal) //for normal non touched state
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside) // "buttonAction" received here
self.view.addSubview(button) //adds subview to display the button
If you need something to easily more around, here is a hacky solution that seems to work. If you need other features from UIButton, this won't be much good.
BarButtonView.swift
import UIKit
class BarButtonView: UIView {
var toolbar = UIToolbar()
var toolbarFrame = CGRect() {
didSet {
display()
}
}
var button = UIBarButtonItem() {
didSet {
display()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
toolbarFrame = frame
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func display() {
toolbar = UIToolbar(frame: toolbarFrame)
toolbar.setBackgroundImage(UIImage(), forToolbarPosition: .Any, barMetrics: .Default)
toolbar.setShadowImage(UIImage(), forToolbarPosition: .Any)
addSubview(toolbar)
let space = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
toolbar.items = [space, button, space]
}
}
In your view controller:
let button = BarButtonView(frame: CGRect(x: 10, y: 10, width: 40, height: 44))
button.button = UIBarButtonItem(barButtonSystemItem: .Trash, target: self, action: nil)
view.addSubview(button)
I am trying to set an Image for bar button Item for that I have an image like:
with resolution 30 * 30 but while I assign this Image to Bar button Its looks like:
I have assigned image this way :
and If I try this way like making an IBOutlet for the button and set Image programatically form this question and code for that is:
// Outlet for bar button
#IBOutlet weak var fbButton: UIBarButtonItem!
// Set Image for bar button
var backImg: UIImage = UIImage(named: "fb.png")!
fbButton.setBackgroundImage(backImg, forState: .Normal, barMetrics: .Default)
but nothing happend with this,
Can anybody tell me what I am doing wrong?
or which is the batter way to do this?
I have achieved that programatically with this code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//create a new button
let button: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
//set image for button
button.setImage(UIImage(named: "fb.png"), forState: UIControlState.Normal)
//add function for button
button.addTarget(self, action: "fbButtonPressed", forControlEvents: UIControlEvents.TouchUpInside)
//set frame
button.frame = CGRectMake(0, 0, 53, 31)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
//This method will call when you press button.
func fbButtonPressed() {
println("Share to fb")
}
}
And result will be:
Same way you can set button for left side too this way:
self.navigationItem.leftBarButtonItem = barButton
And result will be:
And if you want same transaction as navigation controller have when you go back with default back button then you can achieve that with custom back button with this code:
func backButtonPressed(sender:UIButton) {
navigationController?.popViewControllerAnimated(true)
}
For swift 3.0:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//create a new button
let button = UIButton.init(type: .custom)
//set image for button
button.setImage(UIImage(named: "fb.png"), for: UIControlState.normal)
//add function for button
button.addTarget(self, action: #selector(ViewController.fbButtonPressed), for: UIControlEvents.touchUpInside)
//set frame
button.frame = CGRect(x: 0, y: 0, width: 53, height: 51)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
//This method will call when you press button.
func fbButtonPressed() {
print("Share to fb")
}
}
For swift 4.0:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//create a new button
let button = UIButton(type: .custom)
//set image for button
button.setImage(UIImage(named: "fb.png"), for: .normal)
//add function for button
button.addTarget(self, action: #selector(fbButtonPressed), for: .touchUpInside)
//set frame
button.frame = CGRect(x: 0, y: 0, width: 53, height: 51)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
//This method will call when you press button.
#objc func fbButtonPressed() {
print("Share to fb")
}
}
An easy solution may be the following
barButtonItem.image = UIImage(named: "image")
then go to your Assets.xcassets select the image and go to the Attribute Inspector and select "Original Image" in Reder as option.
Similar to the accepted solution, but you can replace the
let button: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
with
let button = UIButton()
Here is the full solution, enjoy: (it's just a bit cleaner than the accepted solution)
let button = UIButton()
button.frame = CGRectMake(0, 0, 51, 31) //won't work if you don't set frame
button.setImage(UIImage(named: "fb"), forState: .Normal)
button.addTarget(self, action: Selector("fbButtonPressed"), forControlEvents: .TouchUpInside)
let barButton = UIBarButtonItem()
barButton.customView = button
self.navigationItem.rightBarButtonItem = barButton
Here's a simple extension on UIBarButtonItem:
extension UIBarButtonItem {
class func itemWith(colorfulImage: UIImage?, target: AnyObject, action: Selector) -> UIBarButtonItem {
let button = UIButton(type: .custom)
button.setImage(colorfulImage, for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 44.0, height: 44.0)
button.addTarget(target, action: action, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
return barButtonItem
}
}
Only two Lines of code required for this
Swift 3.0
let closeButtonImage = UIImage(named: "ic_close_white")
navigationItem.rightBarButtonItem = UIBarButtonItem(image: closeButtonImage, style: .plain, target: self, action: #selector(ResetPasswordViewController.barButtonDidTap(_:)))
func barButtonDidTap(_ sender: UIBarButtonItem)
{
}
I am using latest swift (2.1) and the answer (Dharmesh Kheni and jungledev) does not work for me. The image color was off (when setting in IB, it was blue and when setting directly in UIButton, it was black). It turns out I could create the same bar item with the following code:
let barButton = UIBarButtonItem(image: UIImage(named: "menu"), landscapeImagePhone: nil, style: .Done, target: self, action: #selector(revealBackClicked))
self.navigationItem.leftBarButtonItem = barButton
You can use this code for multiple bar button with custom image:
self.navigationItem.leftBarButtonItem = nil
let button = UIButton(type: .custom)
button.setImage(UIImage (named: "ChatTab"), for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
let button2 = UIButton(type: .custom)
button2.setImage(UIImage (named: "ActivityTab"), for: .normal)
button2.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem2 = UIBarButtonItem(customView: button2)
self.navigationItem.rightBarButtonItems = [barButtonItem, barButtonItem2]
Result will be this:
Initialize barbuttonItem like following:
let pauseButton = UIBarButtonItem(image: UIImage(named: "big"),
style: .plain,
target: self,
action: #selector(PlaybackViewController.pause))
Your problem is because of the way the icon has been made - it doesn't conform to Apple's custom tab bar icon specs:
To design a custom bar icon, follow these guidelines:
Use pure white with appropriate alpha transparency.
Don’t include a drop shadow.
Use antialiasing.
(From the guidelines.)
Something that would be possible looks like this. You can find such icons on most free tab bar icon sites.
Swift 4.
#IBOutlet weak var settingBarBtn: UIBarButtonItem! {
didSet {
let imageSetting = UIImageView(image: UIImage(named: "settings"))
imageSetting.image = imageSetting.image!.withRenderingMode(.alwaysOriginal)
imageSetting.tintColor = UIColor.clear
settingBarBtn.image = imageSetting.image
}
}
SwiftUI
.navigationBarItems modifier takes any view you want:
struct ContentView: View {
var body: some View {
NavigationView {
Text("SwiftUI")
.navigationBarItems(leading:
HStack {
Image(systemName: "trash")
Text("Trash")
}
)
}
}
}
.navigationBarItems(trailing: Image(systemName: "trash") )
.navigationBarItems(leading: Image(systemName: "trash.fill"),
trailing: Image(systemName: "trash")
)
You can use a button for each if you need an action for each of them.
Swift 5+. Smooth solution to add ideal image as you desired dynamic Solution
func rightBarButtonItem(iconNameButton: String, selector: Selector) {
let button = UIButton()
button.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
button.setImage(UIImage(named: iconNameButton), for: .normal)
button.addTarget(self, action: selector, for: .touchUpInside)
button.imageView?.contentMode = .scaleAspectFit
let buttonBarButton = UIBarButtonItem(customView: UIView(frame: CGRect(x: 0, y: 0, width: 25, height: 25)))
buttonBarButton.customView?.addSubview(button)
buttonBarButton.customView?.frame = button.frame
self.navigationItem.rightBarButtonItem = buttonBarButton
}
Just choose Original image option when adding an image to assets in Xcode
If your UIBarButtonItem is already allocated like in a storyboard.
(printBtn)
let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
btn.setImage(UIImage(named: Constants.ImageName.print)?.withRenderingMode(.alwaysTemplate), for: .normal)
btn.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handlePrintPress(tapGesture:))))
printBtn.customView = btn
If you have set up your UIBarButtonItem with an image in the storyboard, one small hack to change the renderingMode is to add the following code to your viewDidLoad(). This way you don't have to resort to adding the entire button and image in code.
if let navButton = self.navigationItem.leftBarButtonItem, let buttonImage = navButton.image {
navButton.image = buttonImage.withRenderingMode(.alwaysOriginal)
}
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Left",
style: .plain,target: self, action: #selector(rightbarButtonAction))
navigationItem.rightBarButtonItem?.image = UIImage(named: "Notification Bell")