UIButton image not resizing - Swift - ios

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)

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

Clickable Image as Nav Bar Title in Swift

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

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)

Swift - UIButton image on bigger screen programmatically

I'm trying to programmatically style my button using swift
let acButton = UIButton.buttonWithType(.Custom) as! UIButton
acButton.frame = CGRectMake(0, 0, buttonWidth, buttonHeight)
acButton.setImage(UIImage(named: "ac"), forState: .Normal)
acButton.imageEdgeInsets = UIEdgeInsetsMake(10,10,10,10)
acButton.layer.borderWidth = 1
acButton.layer.borderColor = UIColor.grayColor().CGColor
acButton.addTarget(self, action: "acPressed", forControlEvents: .TouchUpInside)
self.view.addSubview(acButton)
but i've got little problems on bigger screen devices like iPad Air (see image) the image doesn't fit the button frame, i also tried setting the image as backgroundImage of the button but i didn't get what i want cause imageEdgeInsets doesn't seems to be working on backgroundImage.
Solution:
get the image using imageWithCGImage:scale:orientation, as in the following method:
func getScaledImage(img: UIImage, btn: UIButton) -> UIImage {
// Check which dimension (width or height) to pay respect to and
// calculate the scale factor
var imgRatio: CGFloat = img.size.width / img.size.height
var btnRatio = btn.frame.size.width / btn.frame.size.height
var scaleFactor = (imgRatio > btnRatio) ? img.size.width / btn.frame.size.width : img.size.height / btn.frame.size.height
// Create image using scale factor
var scaledImg = UIImage(CGImage: img.CGImage, scale: scaleFactor, orientation: UIImageOrientation.Up)
return scaledImg!
}
To implement this we would write:
let acImage = getScaledImage(UIImage(named: "ac")!, btn: acButton)
acButton.setImage(acImage, forState: .Normal)
so here the final code:
let acButton = UIButton.buttonWithType(.Custom) as! UIButton
acButton.frame = CGRectMake(0, 0, buttonWidth, buttonHeight)
let acImage = getScaledImage(UIImage(named: "ac")!, btn: acButton)
acButton.setImage(acImage, forState: .Normal)
acButton.imageEdgeInsets = UIEdgeInsetsMake(20, 20, 20, 20)
acButton.addTarget(self, action: "acPressed", forControlEvents: .TouchUpInside)
basicCalculatorView.addSubview(acButton)
have you tried to add constraints? That should scale it just fine.
you might need to set the contentMode of your UIButton:
acButton.contentMode = UIViewContentMode.ScaleAspectFit
Try to set backgroundImage rather than setting just image.
acButton.setBackgroundImage(UIImage(named: "image.jpg"), forState: .Normal)
Check if it works

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