Clickable Image as Nav Bar Title in Swift - ios

I've looked through several threads on here that discuss:
Setting an image for title
Using a button for title
However, I'm trying to combine the two, i.e., clickable image (button) as title.
Unfortunately, while the below code compiles the image doesn't show when assigned as a button. Any suggestions?
func addNavBarImage() {
let navController = navigationController!
let button = UIButton(type: .custom)
var image = UIImage(named: "textLogo")
image = image?.withRenderingMode(.alwaysOriginal)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
let bannerX = bannerWidth / 2 - image!.size.width / 2
let bannerY = bannerHeight / 2 - image!.size.height / 2
button.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
button.imageView?.contentMode = .scaleAspectFit
button.imageView?.image = image
button.addTarget(self, action: #selector(self.logoTapped), for: .touchUpInside)
self.navigationItem.titleView = button
}

create UIImageView, add it as titleView and add UITapGestureRecognizer to your UIImageView
let imageView = UIImageView()
imageView.image = UIImage.named("yourImage")
// do any settings to your imageView
let titleTap = UITapGestureRecognizer(target: self, action: #selector(titlePressed))
self.navigationItem.titleView = imageView
self.navigationItem.titleView?.isUserInteractionEnabled = true
self.navigationItem.titleView?.addGestureRecognizer(titleTap)

Working code for me.
let button = UIButton(type: .custom)
button.setImage(UIImage (named: "your_image"), for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
button.backgroundColor = UIColor.clear
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(self.clickOnButton), for: .touchUpInside)
self.navigationItem.titleView = button
Here you can see in last line button is directly set to the titleView of navigationItem which will add button at the center of navigation bar.
Action method for button is below:
#objc func clickOnButton(button: UIButton) {
print("Title Tapped")
}

Related

How to fit an image in rightbarbuttonitem

I've been trying to put a hamburger button (the three parallel lines) to the right of the titleView in the nav bar, but every time I do, the image I put in covers the entire nav bar and gets rid of the image I have in titleView.
If I select a default image in the storyboard editor it will appear on the right side of the nav bar without any problems, but as soon as I select the hamburger button in the storyboard editor I get the same problem as before. I've tried with multiple different images and I've changed up the code a little bit with no success. Is there a way to resize the image I'm using so it will fit in the nav bar properly or is there just something wrong with my code?
Here is my code from viewController.swift below:
override func viewDidAppear(_ animated: Bool) {
let nav = self.navigationController?.navigationBar
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.contentMode = .scaleAspectFit
let titleImage = UIImage(named: "logowhitecircle")
imageView.image = titleImage
navigationItem.titleView = imageView
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
menuButton.contentMode = .scaleAspectFit
let menuImage = UIImage(named: "hamburgericon")
menuButton.setImage(menuImage, for: .normal)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: menuButton)
You need to set image size in the image assets like 3x = 84px, 2x=56px, 1x = 28px,
see the apple document for more info: https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/custom-icons/
let menuButton = UIBarButtonItem(image: UIImage(named: "logowhitecircle"), style: .plain, target: self, action: #selector(menuButtonTapped(_:)))
self.navigationItem.rightBarButtonItem = menuBu
tton
Try Using below code:
let imageBurger = UIImage(named: "hamburgericon")!
let btnLeftMenu = UIButton(type: .system)
btnLeftMenu.bounds = CGRect(x: 10, y: 0, width: imageBurger.size.width, height: imageBurger.size.height)
btnLeftMenu.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
btnLeftMenu.setImage(imageBurger, for: UIControl.State())
btnLeftMenu.setTitle(title, for: .normal)
let leftButton = UIBarButtonItem(customView: btnLeftMenu)
self.navigationItem.leftBarButtonItem = leftButton
Try this module FFBadgedBarButtonItem it's easy to use module, here is the documenataion Link
Below is my code how to implement it!
let image = UIImage(named: "yourImage")
let finalImage = resizeImage(image: image!, newWidth: 30)
navigationItem.rightBarButtonItem = FFBadgedBarButtonItem(image: finalImage, target: self, action: #selector(rightButtonTouched))
And here is the calling function
#objc func rightButtonTouched() {
// what event you need to perfom by clicking on this button
}
You need to create Bridging Header to work with this Obj-C module.
: D
Try this:
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: "hamburgericon"), forState: UIControlState.Normal)
//add function for button
button.addTarget(self, action: "customButtonPressed", forControlEvents: UIControlEvents.TouchUpInside)
//set frame
button.frame = CGRectMake(0, 0, 40, 40)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
//This method will call when you press button.
func customButtonPressed() {
println("button pressed")
}
}

image and text for nav bar button item. swift

I saw the answer for this question for adding an image to the left nav bar item. And I did it successfully.
But I also want to add a small text next to the image. For example I want to show how many coins the user have. So I need to show a coins image and the number of coins next to it. How can it be done?
I tried to set title (with "123"), but I only see the image and not the title. This my code:
let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named: "coins.png"), for: UIControlState.normal)
button.addTarget(self, action:#selector(self.callMethod), for: UIControlEvents.touchUpInside)
button.frame = CGRect.init(x: 0, y: 0, width: 30, height: 30)
button.setTitle("123", for: UIControlState.normal)
let barButton = UIBarButtonItem.init(customView: button)
self.navigationItem.leftBarButtonItem = barButton
Thanks.
Since the bar button item is initialized with a custom view, you can add a UIImage and a UILabel to one view, along with a UIButton to capture the touch event, and pass that into the initializer.
// the UIButton is simply there to capture touch up event on the entire bar button view.
let button = UIButton.init(type: .custom)
button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
imageView.image = UIImage(named: "coins")
let label = UILabel(frame: CGRect(x: 35, y: 0, width: 50, height: 30))
label.text = "1234"
let buttonView = UIView(frame: CGRect(x: 0, y: 0, width: 90, height: 30))
button.frame = buttonView.frame
buttonView.addSubview(button)
buttonView.addSubview(imageView)
buttonView.addSubview(label)
let barButton = UIBarButtonItem.init(customView: buttonView)
self.navigationItem.leftBarButtonItem = barButton
You might have to adjust the frames accordingly for your own uses, of course.
I think your problem is the width it's 30 try to make it bigger like 50
let buttonContainer:UIView = UIView()
buttonContainer.frame = CGRect(x: 0, y: 0, width: 50, height: 32)
let image = UIImage(named: "coins")
let button = UIButton.init(type: .system)
button.setImage(image, for: .normal)
button.frame = buttonContainer.frame
button.setTitle("sss", for: .normal)
button.addTarget(self, action: #selector(action(_:)), for: .touchUpInside)
buttonContainer.addSubview(button)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: buttonContainer)
You can use backgroundImage for image and setTitle for test to the button.
follow this link definitely you will get idea:
image for nav bar button item swift
Use self.navigationItem.leftBarButtonItems that is an array of UIBarButtonItem
let button = UIBarButtonItem()
let text = UIBarButtonItem()
self.navigationItem.leftBarButtonItems = [button, text]

UIButton image not resizing - Swift

I am creating a custom button with a png image as I have done hundreds of times before.
But for some reason, this time the image isn't scaling with the button size.
func constructInfoViewBtns() {
let buttonsView = UIView.init(frame: CGRectMake(0, 90, self.infoView!.frame.width, 90))
let playPauseBtn = UIButton(type: UIButtonType.Custom) as UIButton
let playPauseBtnImg : UIImage = UIImage(named: "pauseBtn")!
playPauseBtn.setImage(playPauseBtnImg, forState: .Normal)
playPauseBtn.imageView?.contentMode = UIViewContentMode.ScaleAspectFill
playPauseBtn.frame = CGRectMake(0, 0, 55, 55)
playPauseBtn.backgroundColor = UIColor.blueColor()
playPauseBtn.center = CGPointMake(buttonsView.frame.width/2, buttonsView.frame.height/2)
playPauseBtn.addTarget(self, action: "playPauseTrack:", forControlEvents: .TouchDown)
self.playPauseBtn = playPauseBtn
buttonsView.addSubview(self.playPauseBtn!)
self.infoView!.addSubview(buttonsView)
}
What I get is a blue box where the button image is smaller than the button's frame. Like it's padded or something...
add this and try
playPauseBtn.imageEdgeInsets = UIEdgeInsetsMake(25,25,25,25)

How to change Send button image in JSQMessagesController

How can I change JSQMessagesController "Send" button from just String to UIImageView?
Now it looks like:
Can I change this "Send" to image?
I've tried:
let sendButton = JSQMessagesInputToolbar()
sendButton.contentView?.rightBarButtonItem?.imageView?.image = UIImage(named: "send.png")
but I thing it's wrong, because it did not work =/
Create an UIButton and set it as the right bar button item of input toolbar.
let rightButton = UIButton(frame: CGRectZero)
let sendImage = UIImage(named: "send_button.png")
rightButton.setImage(sendImage, forState: UIControlState.Normal)
self.inputToolbar.contentView.rightBarButtonItemWidth = CGFloat(34.0)
self.inputToolbar.contentView.rightBarButtonItem = rightButton
Hope that helps!
No need to create another button, you can reuse the existing one:
override func viewDidLoad() {
super.viewDidLoad()
let imageWidth: CGFloat = 21
let image = UIImage(named: "image-name")
inputToolbar.contentView.rightBarButtonItemWidth = imageWidth
inputToolbar.contentView.rightBarButtonItem.setImage(image, for: .normal)
}
But if you want to have more control of the button, you should create a custom one:
override func viewDidLoad() {
super.viewDidLoad()
let buttonWidth = CGFloat(40)
let buttonHeight = inputToolbar.contentView.leftBarButtonContainerView.frame.size.height
let customButton = UIButton(frame: CGRect(x: 0, y: 0, width: buttonWidth, height: buttonHeight))
customButton.backgroundColor = .red
customButton.setImage(UIImage(named: "send-message"), for: .normal)
customButton.imageView?.contentMode = .scaleAspectFit
inputToolbar.contentView.rightBarButtonItemWidth = buttonWidth
inputToolbar.contentView.rightBarButtonItem = customButton
}
It can be set directly using the rightBarButtonItem. Your code is not working cause you are not setting the state of the button.
self.inputToolbar?.contentView.rightBarButtonItem?.setImage(UIImage(named: "send"), for: .normal)

image for nav bar button item swift

I want to display an image in the left hand side of my nav bar in swift.
I have tried adding a nav bar button item and setting an image there.
The problem is that I have to use a really small image for it to fit in the nav bar nicely. But making such a small image leads to pixelation especially on the bigger phone iPhone 6 and 6 Plus.
Is there a way to use a good quality image and then set the frame to fit within the bounds of the nav bar?
My attempt:
var image = UIImage(named: "Harp.png")
image = image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItem.frame = CGRectMake(0, 0, 53, 31)
//image.frame = CGRectMake(0, 0, 53, 31)
I tried putting the frame on the image first and then on the bar button item.
But this is throwing up an error:
Type of expression is ambiguous without more context.
Try This
let button = UIButton(type: UIButtonType.Custom)
button.setImage(UIImage(named: "yourImageName.png"), forState: UIControlState.Normal)
button.addTarget(self, action:Selector("callMethod"), forControlEvents: UIControlEvents.TouchDragInside)
button.frame=CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItems = [newBackButton,barButton]
For Swift 3
let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named: "yourImageName.png"), for: UIControlState.normal)
button.addTarget(self, action:#selector(ViewController.callMethod), for:.touchUpInside)
button.frame = CGRect.init(x: 0, y: 0, width: 30, height: 30) //CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem.init(customView: button)
self.navigationItem.leftBarButtonItem = barButton
Swift 4
let button = UIButton(type: UIButton.ButtonType.custom)
button.setImage(UIImage(named: "getstarted"), for: .normal)
button.addTarget(self, action:#selector(callMethod), for: .touchDragInside)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItems = [barButton]
Here is action
#objc func callMethod() {
//do stuff here
}
Use this code:
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]
Output:
Swift 5, XCode 11 to make Navigation Bar Item with rounded image, image from assets or to download from URL.
1) New file: UIBarButtonItem+RoundedView.swift
import Foundation
class ImageBarButton : UIView {
var imageView: UIImageView!
var button: UIButton!
convenience init(withUrl imageURL: URL? = nil, withImage image: UIImage? = nil, frame: CGRect = CGRect(x: 0, y: 0, width: 40, height: 40)) {
self.init(frame: frame)
imageView = UIImageView(frame: frame)
imageView.backgroundColor = .white
imageView.layer.cornerRadius = frame.height/2
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
addSubview(imageView)
button = UIButton(frame: frame)
button.backgroundColor = .clear
button.setTitle("", for: .normal)
addSubview(button)
if let url = imageURL { // you can use pods like Nuke or Kingfisher
URLSession(configuration: .default).dataTask(with: URL(string: imageUrl)!) {[weak self] (data, response, error) in
if let data = data , let image = UIImage(data: data) {
DispatchQueue.main.async {
self?.imgView.image = image
}
}
}.resume()
} else if let image = image {
self.imageView.image = image
}
}
func load()-> UIBarButtonItem {
return UIBarButtonItem(customView: self)
}
}
2) Add navigation bar items, you can use navigationItem.rightBarButtonItems, navigationItem.leftBarButtonItems:
private func initalizeNavigationBarItems() {
let searchBarButtonView = ImageBarButton(withImage: #imageLiteral(resourceName: "greenSearchIcon")) // Assets
searchBarButtonView.button.addTarget(self, action: #selector(presentSearchViewController), for: .touchUpInside)
if let user = AccountManager.currentUser, let userProfilePictureURL = user.imageUrl { // API Url
let profileBarButtonView = ImageBarButton(withUrl: userProfilePictureURL)
profileBarButtonView.button.addTarget(self, action: #selector(presentMoreViewController), for: .touchUpInside)
navigationItem.rightBarButtonItems = [searchBarButtonView.load(), profileBarButtonView.load()]
} else {
let profileBarButtonView = ImageBarButton(withImage: #imageLiteral(resourceName: "profileIcon"))
profileBarButtonView.button.addTarget(self, action: #selector(presentMoreViewController), for: .touchUpInside)
navigationItem.rightBarButtonItems = [searchBarButtonView.load(), profileBarButtonView.load()]
}
}
#objc func presentMoreViewController(_ sender: Any) {
// present MoreViewController
}
#objc func presentSearchViewController(_ sender: Any) {
// present SearchViewController
}
Preview
Swift 4 and 5:
let imageView = UIImageView(image: UIImage(named: "Harp"))
let buttonItem = UIBarButtonItem(customView: imageView)
self.navigationItem.leftBarButtonItem = buttonItem
There is a way to use images of different sizes, depending on the device. It's called an Asset Catalog. You'll probably already have one in your project, or if not, you can add one with File > New > File > Resource > Asset Catalogue.
Within your Asset Catalog, you can have multiple 'Image Sets' (these will be shown down the left-hand side). Add a new Image Set with the '+' at the bottom. For each Image Set, you can supply different images (e.g. of different sizes) for each of #1x, #2x, and #3x.
Then, to use one of these images in code, you simply use UIImage(named: "name_of_image_set") - note no extension. The correct image will be loaded, depending on the device.
Hope this helps!
Swift 5
You need to use constraints to properly set up nav bar button with image.
let button = UIButton(type: .custom)
button.setImage(UIImage(named: yourImageName), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: 40).isActive = true
button.heightAnchor.constraint(equalToConstant: 40).isActive = true
let barButton = UIBarButtonItem(customView: button)
navigationItem.rightBarButtonItem = barButton

Resources