Resizing UIButton height with code? - ios

I am trying to set a clickable "textonly"-button but right now I'm having problem fixing the height for my button. Before all this I tried having it as an label, but then the touchhandling gets complicated so I decided to just do a button with no frame etc..
So now I need to set the buttonheight to the Text thats inside, any ideas?
Heres a code snippet:
//...
button.setTitle("Log in", for: .normal)
button.setTitleColor(.white, for: .normal)
button.layer.borderWidth = 0
button.frame = CGRect
button.addTarget(self, action: #selector(LoginFunction), for: .touchUpInside)
//...

If you want multiple lines of text in your UIButton you should set yourButton.titleLabel?.numberOfLines = 0 and yourButton.titleLabel?.lineBreakMode = .byWordWrapping. You will get multiline button, which height you can configure as you want.
Also you calculate frame of your text you should use
let context = NSStringDrawingContext()
let frame = yourText.boundingRectWithSize(
CGSize(width: yourButtonWidth, height: 9999),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: dictionaryOfYourTextAttributes, context: context)

You should still have a frame for the button to be displayed in the UI. It define yours button position and size (including height). Here is an example for button with position (0,0) and size (100,100):
button.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
Maybe what you mean by "frame" is "border". You can achieve borderless button by setting borderWidth to 0, which you already did in your code.
button.layer.borderWidth = 0
If you want to set size for the text you can do:
button.titleLabel?.font = UIFont.systemFont(ofSize: 17)

Related

add bottom line to UIButton - Swift

I use the extension to UIButton and I added it to my UIButton but I still can't see the line.
I'm missing something, please help
extension:
https://gist.github.com/Isuru-Nanayakkara/496d5713e61125bddcf5
my code:
let settingsButton : UIButton = {
let button = UIButton()
button.setTitle("Settings", for: .normal)
button.setTitleColor(.white, for: .normal)
button.addBorder(side: .Bottom, color: .white, width: 100)
return button
}()
I want to get something like this:
Add a UIView that has [x] points height and same width as the button, and its y position is the same as the height of the button.
let frame = CGRect(x: 0, y: button.frame.size.height, width: button.frame.size.width, height: 2)
let borderBottom = UIView(frame: frame)
borderBottom.backgroundColor= UIColor.white
button.addSubview(borderBottom)

Swift: Radio button into StackView are not displayed properly

I created a list of radio button in a stackView, but I do not understand why they are displayed wrong, they are not properly aligned
I want all my buttons to be correctly aligned on the left as I can solve this problem thank you!
Here is a part of the code:
var buttons = [UIButton]()
var titles = ["Lasy", "What I've been told", "I'm do into it", "Close the best i can", "Hard core"]
func setupUI() {
for title in titles {
// create button
let button = UIButton(type: .custom)
button.setTitleColor(.black, for: .normal)
button.setTitle(title, for: .normal)
button.setImage(UIImage(named: "uncheck.png")!, for: .normal)
// if the selected button cannot be reclick again, you can use .Disabled state
button.setImage(UIImage(named: "check.png")!, for: .selected)
button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 35)
button.addTarget(self, action: #selector(radioButtonAction), for: .touchUpInside)
buttons.append(button)
}
for button in buttons {
addArrangedSubview(button)
}
setupUserChoice()
}
func setupUserChoice(){
if titles.contains(value) {
let valueIndex = titles.index(of: value)
radioButtonAction(sender: buttons[valueIndex!])
}
}
func setStackView() {
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.distribution = .fill
stackView.spacing = 16.0
stackView.alignment = .leading
}
The problem is with the way you are trying to set the imageEdgeInsets. It is only adjusting the image position, not increasing the size of the button accordingly. For increasing the size of the button, you need to set contentEdgeInsets. But you also need to adjust the title position according to the change in image's position. You can use titleEdgeInsets for that.
So remove you code button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 35) and replace it with :-
let leftPadding_beforeImage: CGFloat = 35
let gapBetweenImageAndTitle: CGFloat = 8
let rightPadding_afterTitle: CGFloat = 16
button.imageEdgeInsets = UIEdgeInsetsMake(0, leftPadding_beforeImage, 0, 0)
button.titleEdgeInsets = UIEdgeInsetsMake(0, (leftPadding_beforeImage+gapBetweenImageAndTitle), 0, -(leftPadding_beforeImage+gapBetweenImageAndTitle))
button.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, (leftPadding_beforeImage+gapBetweenImageAndTitle+rightPadding_afterTitle))
I hope the variable names are self-explanatory. If you want to know more about UIButton edgeInsets, I suggest you reading this fantastic answer.
Set the frame of each button, because UIStackViews use intrinsic content size. for example :
button.frame = CGRect(x: 0, y: 0, width: 100, height: 20)

UIScrollView cannot scroll horizontally

I have a UIScrollView inside a UIViewController and I expect it to be scrolled horizontally. I programmatically add button to the ScrollView by a loop. After the loop, I set the myScrollView.contentSize.width to be buttonWidth * numberOfButtons. I also double check to make sure that contentSize is bigger than the scrollview's frame (in this case the scrollview has width of 375).
let numberOfButton = 7
for index in 0..<numberOfButton {
let button = UIButton()
let frame = CGRect(x: 80 + (index * 80), y: 6, width: 60, height: 32)
button.setTitle("Button" + String(index), forState: .Normal)
button.frame = frame
button.titleLabel?.font = UIFont(name: "Museo Sans", size: 16)
button.setTitleColor(UIColor.blueColor(), forState: .Normal)
myScrollView.addSubview(button)
}
myScrollView.contentSize = CGSize(width: 100*numberOfButtons, height: 42)
When I run the code, it only appears to the Button3 (there are 7 buttons) and I cannot scroll it to the end. However, when I set myScrollView.bounces = true I can drag the scrollview around and see other buttons but it will bounce back to the original state. Any help would be much appreciated.
I think your problem is setting the X value on the first button. I have just tried this code and it works fine
let numberOfButtons = 7
for index in 0..<numberOfButtons {
let button = UIButton()
let frame = CGRect(x: 8 + (index * 96), y: 6, width: 80, height: 32)
button.setTitle("Button \(index)", for: .normal)
button.frame = frame
button.titleLabel?.font = UIFont(name: "Museo Sans", size: 16)
button.setTitleColor(UIColor.blue, for: .normal)
myScrollView.addSubview(button)
}
myScrollView.contentSize = CGSize(width: 100*numberOfButton, height: 42)
Change this
tagBar.contentSize = CGSize(width: 100*7, height: 42)
to
myScrollView.contentSize = CGSize(width: 100*7, height: 42)
The answer that Rajeshkumar R gave you, or better use constraints. You can set a constraint between the left of myScrollView and the left your first button (a "leading space" constraint), then a leading space constraint between each button and the previous one, and when you finish looping, a trailing space from your last button to the myScrollView.
This way you don't have to calculate the contentSize yourself. It's also more extensible (for example, if you had buttons of different sizes, you would have to know each width, sum them all, then sum the margins between elements and between the first and the last one with the scrollView…).

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)

Resources