[ios] How to set image for bar button with swift?

I am trying to set an Image for bar button Item for that I have an image like:

enter image description here

with resolution 30 * 30 but while I assign this Image to Bar button Its looks like:

enter image description here

I have assigned image this way :

enter image description here

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?

This question is related to ios swift uiimage uibarbuttonitem

The answer is


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:

enter image description here

Same way you can set button for left side too this way:

self.navigationItem.leftBarButtonItem = barButton

And result will be:

enter image description here

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.


Just choose Original image option when adding an image to assets in Xcode

enter image description here


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
    }
}

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)
}

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

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

Initialize barbuttonItem like following:

let pauseButton = UIBarButtonItem(image: UIImage(named: "big"),
                                  style: .plain,
                                  target: self,
                                  action: #selector(PlaybackViewController.pause))

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:

enter image description here


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) 
{

}

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")
                }
            )
        }
    }
}

Leading with text[1]

.navigationBarItems(trailing: Image(systemName: "trash") )

Trailing

.navigationBarItems(leading: Image(systemName: "trash.fill"),
                    trailing: Image(systemName: "trash")
)

Bothsides

You can use a button for each if you need an action for each of them.


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.

Button example


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

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
    }
}

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to swift

Make a VStack fill the width of the screen in SwiftUI Xcode 10.2.1 Command PhaseScriptExecution failed with a nonzero exit code Command CompileSwift failed with a nonzero exit code in Xcode 10 Convert Json string to Json object in Swift 4 iOS Swift - Get the Current Local Time and Date Timestamp Xcode 9 Swift Language Version (SWIFT_VERSION) How do I use Safe Area Layout programmatically? How can I use String substring in Swift 4? 'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator Safe Area of Xcode 9 The use of Swift 3 @objc inference in Swift 4 mode is deprecated?

Examples related to uiimage

Crop image to specified size and picture location Convert UIImage to NSData and convert back to UIImage in Swift? How can I color a UIImage in Swift? How to Resize image in Swift? How to set image for bar button with swift? How do you create a UIImage View Programmatically - Swift Navigation bar with UIImage for title Loading/Downloading image from URL on Swift How can I change image tintColor in iOS and WatchKit UIImageView aspect fit and center

Examples related to uibarbuttonitem

UIBarButtonItem in navigation bar programmatically? Change color of Back button in navigation bar How to set image for bar button with swift? How to set the action for a UIBarButtonItem in Swift Removing the title text of an iOS UIBarButtonItem How do I show/hide a UIBarButtonItem? Add button to navigationbar programmatically Setting action for back button in navigation controller