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
Related
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")
}
Is it possible to set corner radius to make UIButton circle using different height and width of UIButton in Swift.
let button = UIButton(frame: CGRectMake(0, 0, 60, 40))
button.layer.cornerRadius = button.layer.bounds.size.width / 2
button.layer.masksToBounds = true
It won't work because button with different height and width. Please tell me if there is any other approach because button height and width going to be update. I need to make the button always be a circle.
TRY THIS:
let myFirstButton = UIButton()
myFirstButton.setTitle("SUBMIT", forState: .Normal)
myFirstButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
myFirstButton.frame = CGRectMake(15, 50, 100, 100)
myFirstButton.layer.cornerRadius = yourButton.bounds.size.width / 2
self.view.addSubview(myFirstButton)
Make a file with name CircularButton
paste the code below class
implement this class on the button on storyboard
Example:
import UIKit
class CircularButton: UIButton {
override func awakeFromNib() {
self.layer.cornerRadius = self.frame.size.width/2
self.clipsToBounds = true
self.layer.borderColor = UIColor.lightGray.cgColor
self.layer.borderWidth = 0.5
}
}
I have a PDF file in my image assets file in my Xcode project. I'm trying to create a bar button item that uses that PDF image. But whenever I set the image property in Interface Builder to the image it takes over most of my tab bar and removes the title.
I have a left bar button item with the system item stop. So it looks like an X icon. I would like to do the same thing on the right side with my settings PDF image I have.
Is there a way to fix this sizing issue within Interface Builder? If not how can I fix this in code?
Using Code what I do when the image size is too big, I resize the UIImage before rendering/setting on the UIControl. I have this extension on UIImage that helps re-scale an image.
// MARK: - Used to scale UIImages
extension UIImage {
func scaleTo(_ newSize: CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage ?? self
}
}
Using this would look like this
let defaultImage = UIImage(named: "someimagenamehere")?
.scaleTo(CGSize(width: 40, height: 40))
self.navigationItem.leftBarButtonItem = UIBarButtonItem(
image: defaultImage,
style: .plain,
target: self,
action: #selector(self.someselectorhere(_:)))
UPDATE: This is what it would look like using #IBDesignable and #IBInspectable
#IBDesignable
class CustomBarButtonItem: UIBarButtonItem {
#IBInspectable
var scaledHeight: CGFloat = 0 {
didSet {
self.image = self.image?.scaleTo(CGSize(width: self.scaledHeight, height: self.scaledWidth))
}
}
#IBInspectable
var scaledWidth: CGFloat = 0 {
didSet {
self.image = self.image?.scaleTo(CGSize(width: self.scaledHeight, height: self.scaledWidth))
}
}
}
The accepted solution is a good approach. However, in my case, I had one item pdf and the rest where png. I faced also the issue of working on a started project and all the icons were different sizes.
I ended up doing:
extension UIBarButtonItem {
convenience init(image: UIImage?, size: CGSize, tintColor: UIColor, target: Any?, action: Selector?) {
let holderView = UIButton()
let button: UIButton = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
holderView.addSubview(button)
button.centerYAnchor.constraint(equalTo: holderView.centerYAnchor).isActive = true
button.centerXAnchor.constraint(equalTo: holderView.centerXAnchor).isActive = true
button.heightAnchor.constraint(equalToConstant: size.height).isActive = true
button.heightAnchor.constraint(equalToConstant: size.width).isActive = true
button.setImage(image?.withRenderingMode(.alwaysTemplate), for: .normal)
button.imageView?.contentMode = .scaleAspectFit
button.tintColor = tintColor
if let target = target, let action = action {
button.addTarget(target, action: action, for: .touchUpInside)
}
self.init(customView: holderView)
}
}
I hope it helps
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 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)