Change a SF Symbol size inside a UIButton - ios

I am declaring a Button like this :
let menuButton = UIButton()
After that I am trying to change it's parameter and set his position on the view with the help of LBTATools (a pod) with this function:
fileprivate func setMenuButtonUI() {
menuButton.setImage(UIImage(systemName: "line.horizontal.3.decrease.circle.fill"), for: .normal)
view.addSubview(menuButton)
menuButton.anchor(top: view.safeAreaLayoutGuide.topAnchor, leading: view.leadingAnchor, bottom: nil, trailing: nil, padding: .init(top: 20, left: 60, bottom: 0, right: 0), size: .init(width: 40, height: 40))
menuButton.setupShadow(opacity: 1, radius: 5, offset: .zero, color: .darkGray)
menuButton.tintColor = .red
}
Everything is working well, I get the right color, position and even size.
Only problem is it's size, I cannot change it with all the usual methods like menuButton.imageView?.contentMode = .scaleAspectFit etc..
Probably it comes from the fact that it is a SF Symbol and not a normal image.
The help of someone would be really appreciated.
Thanks

You can do it using SymbolConfiguration like in the sample code below:
let largeConfig = UIImage.SymbolConfiguration(pointSize: 140, weight: .bold, scale: .large)
let largeBoldDoc = UIImage(systemName: "doc.circle.fill", withConfiguration: largeConfig)
button.setImage(largeBoldDoc, for: .normal)

The iOS 15 and Swift 5 solution would be:
var config = UIButton.Configuration.plain() // Change style with e.g. `.filled()`
config.title = "Title of the UIButton"
config.image = UIImage(systemName: "line.horizontal.3.decrease.circle.fill",
withConfiguration: UIImage.SymbolConfiguration(scale: .small)) // Change the scale here
config.imagePadding = 4 // Padding between image and title
let menuButton = UIButton()
menuButton.configuration = config

Objective C:
UIImageSymbolConfiguration * configuration = [UIImageSymbolConfiguration configurationWithPointSize:30 weight:UIImageSymbolWeightBold scale:UIImageSymbolScaleLarge];
UIImage * image = [UIImage systemImageNamed:#"" withConfiguration:configuration];
[_btn setImage:image forState:UIControlStateNormal];

Related

IOS 15 UIButton right alignment not working

In IOS 15, Even after setting button text alignment to right, it leaves little space after the button title text.
As shown in the following image it leaves the space after the word Test.
How can I remove this space? I want the letter "t" in the text to touch the trailing of the button.
In ios 14 and below it looks like this
This is a little trick or you can do it with UIButton.Configuration, set your button like this:
let myButton: UIButton = {
let b = UIButton()
b.backgroundColor = .white
b.tintColor = .black
b.layer.cornerRadius = 8
b.clipsToBounds = true
b.setTitle(" My button Test", for: .normal) // space in front of string = space fron text and image
b.setTitleColor(.black, for: .normal)
b.titleLabel?.font = .systemFont(ofSize: 17, weight: .regular)
b.contentHorizontalAlignment = .right
b.setImage(UIImage(systemName: "bag"), for: .normal)
b.configuration?.imagePlacement = .leading // use button configuration to add image position
b.translatesAutoresizingMaskIntoConstraints = false
return b
}()
This is UIButton.Configuration style:
let myButton: UIButton = {
var filled = UIButton.Configuration.filled()
filled.title = "My button Test"
filled.buttonSize = .large
filled.baseBackgroundColor = .white
filled.baseForegroundColor = .black
filled.cornerStyle = .medium
filled.image = UIImage(systemName: "bag", withConfiguration: UIImage.SymbolConfiguration(scale: .large))
filled.imagePlacement = .leading
filled.imagePadding = 4
filled.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
let b = UIButton(configuration: filled, primaryAction: nil)
b.contentHorizontalAlignment = .right
b.translatesAutoresizingMaskIntoConstraints = false
return b
}()
in viewDidLoad present button and set constraints:
view.addSubview(myButton)
myButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
myButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
myButton.widthAnchor.constraint(equalToConstant: 200).isActive = true
This is the result:
You can try using this with DispatchQueue
button.contentHorizontalAlignment = .left
emailBtn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
try set both:
button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 25, bottom: 0, right: 00)
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 00)

How to get Inset Buttons like that of iOS Maps app modal?

Swift 4.2 implemented views programmatically only
I have created a stack view and put four buttons in it but they are just simple buttons without any gray background.
I want to achieve the exact four buttons in my stackview equally centered as like as -
button.contentEdgeInset //Not working
This is what I tried -
let feedbackButton:UIButton = {
let origImage = UIImage(named: "feedback")
let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.translatesAutoresizingMaskIntoConstraints = false
button.setBackgroundImage(tintedImage, for: UIControl.State.normal)
button.tintColor = .systemPinkColor
button.layer.cornerRadius = 7
button.backgroundColor = UIColor.lightGray.withAlphaComponent(0.5)
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
// button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 50, bottom: 0, right: 50)
// button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 50, bottom: 0, right: 50)
button.clipsToBounds = true
button.addTarget(self, action: #selector(feedbackFaculty), for: .touchUpInside)
return button
}()
Output -
The button's image gets stretched along with insets. button.imageInsets and button.titleInsets not working.
Help me out. Thanks!
The background image doesn't follow the content insets. So this line:
button.setBackgroundImage(tintedImage, for: UIControl.State.normal)
needs to be changed to:
button.setImage(tintedImage, for: .normal)
Also, here's a couple things to note (per Apple's UIButton documentation):
Supply a title string or image; size the button appropriately for your content.
Which implies that you cannot set an image and title at the same time, this might be why you're noticing titleInset and imageInset not playing nicely.
However, if you just set appropriate constraints for the buttons and set insets for the title OR the image you should be able to get the look you want. Also make sure your stack view is configured to use equal spacing for it's distribution.
The imageInset for each button in the image below is (20, 20, 20, 20).

Resizing a background image on UIButton

I am trying to add a "calendar day" image to surround some text on a clickable UI button like so:
let button = UIButton()
let X_Offset : CGFloat = (95 * CGFloat(buttonCount) ) + 10
let scrollHeight = scrollView.bounds.height
button.frame = CGRect(x: X_Offset, y: scrollHeight/6, width: 70, height: 60)
let buttonText = event.startTime.toShortDayOfWeekString() + "\n" + event.startTime.toShortDayOfMonthString()
button.titleLabel!.lineBreakMode = .byWordWrapping
button.titleLabel!.textAlignment = .center
button.setTitle(buttonText, for: .normal)
button.tag = i
button.backgroundColor = CompanyColor.Red.color
let image = UIImage(named: "calendarDay")
button.setBackgroundImage(image, for: .normal)
button.titleLabel?.font = UIFont(name: "Roboto", size: 14)
button.layer.cornerRadius = 8
button.clipsToBounds = true
But the image is encroaching on the text a bit too much:
How can I get the background image to scale up slightly and leave enough gap for the text?
I think what you what you are looking for is setting imageEdgeInsets for UIButton. Setting of these properties lets you move image around besides its default position. You have to play around to get your desired result.
There are two ways you can do this. One is using Interface Builder and other one is programmatically. Interface builder is easiest way to go I guess. Below image shows how can you set those properties for UIButton.
or try using programmatically like this
button.imageEdgeInsets = UIEdgeInsets(top: -10, left: 32, bottom: -10, right: 50)
You can move title like this
button.titleEdgeInsets = UIEdgeInsets(top: 0, left:0, bottom: 0, right: 20)
Note: Setting UIEdgeInsets like this might have different result if you have dynamic size button e.g. for different screen size. Always make sure that it looks as expected for all screen sizes.

How to resize an image inside an UIButton programmatically?

I have this UIButton and an image to fit in.
I don't want that the image take all the space inside the button but just a little part of it right in the center, but if I resize the button it will resize the image too.
How can I do that, is there an option to set whatever dimension I want independently from the size of the UIButton?
Thanks!
This can be done through code in the following way:
let imageSize:CGSize = CGSize(width: 20, height: 20)
let button:UIButton = UIButton(type: UIButton.ButtonType.custom)
button.frame = CGRect(x: 200, y: 200, width: 60, height: 60)
button.backgroundColor = UIColor.yellow
button.setImage(UIImage(named: "chat.png"), for: UIControl.State.normal)
// The below line will give you what you want
button.imageEdgeInsets = UIEdgeInsets(
top: (button.frame.size.height - imageSize.height) / 2,
left: (button.frame.size.width - imageSize.width) / 2,
bottom: (button.frame.size.height - imageSize.height) / 2,
right: (button.frame.size.width - imageSize.width) / 2)
self.view.addSubview(button)
This way, you can achieve what you wanted.
I couldn't get the button's imageView to resize until I used contentHorizontalAlignment and contentVerticalAlignment both set to .fill. Then using imageEdgeInsets I repositioned the image.
let button = UIButton()
let image = UIImage(systemName: "bag.badge.plus")
button.setImage(image, for: .normal)
button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageEdgeInsets = UIEdgeInsets(top: 6, left: 6, bottom: 10, right: 10)
Result:
You can experiment with image view insets. Every UIButton has a property imageView.
In Swift 3 you can do this like so:
//let button = UIButton()
button.imageView?.backgroundColor = UIColor.red
button.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10)
red background is just so you know what is changing
I would do it this way:
A UIButton is just a UIView. You can simply add a UIImageView with a set image and call addSubview on the UIButton.
Taking into account what KVISH said before i have implemented this and it worked as expected. I posted this because Houman asked for an example.
//grab the image using the name of the pic
var image = UIImage(named: "picture")
//set the size for the image
image = image?.resize(toWidth: 18)
image = image?.resize(toHeight: 18)
//set the image to the button
buttonName.setImage(image, for: UIControlState.normal)
//adjust the position
buttonName.imageEdgeInsets = UIEdgeInsetsMake(8,16,9,0)
As of iOS 13, when using SF Symbols, I prefer this:
let button = UIButton()
let font = UIFont.systemFont(ofSize: 30) // <- make it larger, smaller, whatever you want.
let config = UIImage.SymbolConfiguration(font: font)
let image = UIImage(systemName: "bag.badge.plus", withConfiguration: config)
button.setImage(image, for: .normal)
These can be achieved by adding imageEdgeInsets to a UIButton.
In swift4.2
button.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)

How to set image and text in front of gradientLayer on UIButton?

My code looks like this:
pickerCountry = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
pickerCountry.frame = CGRectMake(self.view.frame.size.width/2 - pickerCountry.frame.size.width, 50, 100, 100)
pickerCountry.center.x = self.view.center.x
pickerCountry.setTitle("Start1", forState: UIControlState.Normal)
pickerCountry.setImage(UIImage(named: "Britain_mdpi.png"), forState: UIControlState.Normal)
pickerCountry.tintColor = UIColor.blackColor()
pickerCountry.titleLabel?.tintColor = UIColor.blackColor()
pickerCountry.layer.cornerRadius = 2
pickerCountry.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 200)
pickerCountry.titleEdgeInsets = UIEdgeInsets(top: 5, left: 50, bottom: 5, right: 5)
pickerCountry.addTarget(self, action: "countryPicker:", forControlEvents: UIControlEvents.TouchUpInside)
ContentView.addSubview(pickerCountry)
and I add gradient in a func like this:
let colorTop = UIColor(netHex:0xffffff).CGColor
let colorBottom = UIColor(netHex:0xebebeb).CGColor
pickerCountryGradientLayer.masksToBounds = true
pickerCountryGradientLayer.cornerRadius = pickerCountry.layer.cornerRadius
pickerCountryGradientLayer.colors = [ colorTop, colorBottom]
pickerCountryGradientLayer.locations = [ 0.0, 1.0]
pickerCountry.layer.insertSublayer(pickerCountryGradientLayer, below: pickerCountry.imageView?.layer)
When I use this last line, insertSublayer like this I see the image, and I sort of see the title, but its color is white, or something, kind of weird. I set the color to black, so if this really does work, how do I change the title color?
I tried using addSublayer, but then I see title label and not the image.
You mention you've set your UIButton's title color but I don't see where you're setting your UIButton's title color. Use:
pickerCountry.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)

Resources