How to make button width based on text length? - swift

I want to find a way, how to calculate button width based on text size? As I am using localize for translations, so based on different languages, button text changes, and some of them does not fit into the button size.

If you work with autolayout
it's quite easy. You just need to make sure that the constraints that specify the x coordinate (like leading space resp. trailing space, also width) have a lower priority than the value for the horizontal content compression resistance priority.
If you do manually
You can calculate the size of the text with:
guard let buttonFont = button.titleLabel?.font else { return }
let buttonText = "click me"
let size = t.size(withAttributes:[.font: buttonFont])
and then set the button's frame size:
button.frame.size = size

Related

How to smoothly change text in UILabel

I have some UILabels next to each other containing text.
It could be:
2x-5 = 3
I can drag "-5" to the other side.
2x = 3-5
It then moves in to place next to "3" and then I change the sign from - to +, within a UIView.animate() function.
Because "+" is a little bit wider than "-" the text goes past the limits of the UILabel, which cuts of the text in one side.
So I resize the labels width, but it is visible when using the application.
I have tried changing the size of the label before I change the sign, just adding a lot of space.
But it still cuts some of the text off.
Here is the code:
let v = UILabel()
v.text = "+5"
UIView.animate(withDuration: 0.5, animations: {
v.frame.size.width = v.intrinsicContentSize.width + 20
v.text = "-5"
v.font = UIFont.boldSystemFont(ofSize: 45)
v.textAlignment = .center
v.frame.size.width = v.intrinsicContentSize.width
v.frame.size.height = v.intrinsicContentSize.height
}
Optimally I want the label not to cut off any of the text when the width of the text is changed.
(Edit: removed other question unrelated to main question)
Thank you in advance for any help!

How can I scale font size based on watch size in WatchKit?

I have an Apple Watch app that I would like to scale the font size for depending on the screen size. Currently, the only way I found to scale the font size is based on setting the device variation for each size in the storyboard. However, I was wondering if there was a way around this. I'm hoping for a way to scale the font size based the on screen size automatically. Any tips or suggestions are appreciated.
You should multiply the font size with the current width of the screen and divide the product with a reference screen size of your choice (in this example, it's the 38mm size, which has the width of 136 logical pixels).
let label = WKInterfaceLabel()
let fontSize: CGFloat = 12
let scaledFontSize = fontSize * WKInterfaceDevice.current.screenBounds.width / 136
let font = UIFont.systemFont(ofSize: scaledFontSize)
let attrString = NSAttributedString(string: "Example Text", attributes: [.font: font])
label.setAttributedText(attrString)

How to change image's size? Image does not fill

I'm trying to make the image rounded. It is already 128x128 (width and height) and the corner radius is 64. I want to zoom in before cutting the photo to take the full rounded size of the picture.
How to zoom it?
My code:
profileImage.layer.cornerRadius = 64
profileImage.clipsToBounds = true
I want to make it like this:
You should set the UIImageView's content mode to .scaleAspectFill. That way, the image will fill up the whole container without distorting it.
profileImage.contentMode = .scaleAspectFill
please first ensure your image height and width must be equal. and constraint set properly
after that change below to line
profileImage.layer.cornerRadius = profileImage.frame.size.width/2
profileImage.clipsToBounds = true

How can I add a list of offset checkboxes to an NSScrollView?

I have an NSScrollView that I am trying to populate with check boxes (NSButton / NSToggleButton). The number of checkboxes I add should be equal to a number of items in an array. This part is working.
The following code successfully adds the checkboxes to the scroll view, but they are all on top of each other. I am trying to add them, but offset from each other in a "list view" manner such as a tableview on iOS. Here's my code:
for calendar in self.allCalendars {
self.allCalendars.append(calendar as EKCalendar)
let checkbox = NSButton.init(checkboxWithTitle: calendar.title, target: self, action: #selector(self.checkboxDidChange))
checkbox.setButtonType(NSToggleButton)
self.checkboxArray.append(checkbox as NSButton)
self.addSubview(checkbox)
}
And here's a screenshot of the result:
Here is something that you could implement, it would change how you do your loop so that you have an index of each iteration, but it can help you calculate some sort of vertical spacing:
for i in 0 ..< allCalendars.count {
let margin: CGFloat = 5.0 // Or whatever you want the padding on the left to be
let vertSpacing: CGFloat = 10.0 // However much separation you want in between boxes
self.allCalendars.append(allCalendars[i] as EKCalendar)
let checkbox = NSButton.init(checkboxWithTitle: allCalendars[i].title, target: self, action: #selector(self.checkboxDidChange))
checkbox.setButtonType(NSToggleButton)
// Now you can set the frame of the checkbox within it's superview's coordinate system
// This calculates it based on the bounds.height, if you want to use a custom height, substitute that.
checkbox.frame = CGRect(x: margin, y: vertSpacing + (vertSpacing + checkbox.bounds.height)*CGFloat(i), width: checkbox.bounds.width, height: checkbox.bounds.height)
self.checkboxArray.append(checkbox as NSButton)
self.addSubview(checkbox)
}
Basically what that y-value vertSpacing + (vertSpacing + checkbox.bounds.height)*CGFloat(i) does is it starts the very first checkbox off with a y-pos of whatever you set your vertical spacing value to be, and then for every checkbox after, it will set it one vertical space value below the previous checkbox. This solution will assume that each checkbox is of the same height. You can set a custom height if you don't want to use the bounds.height value.

UILabel sizeThatFits returns different values for different devices. Why?

In my swift project I need to resize a UILabel to fit a text. I use sizeThatFits to calculate the size. However the results vary enormously among the devices. The width is limited to 280 points. For iPhone 5/s the height is calculated to 19 but for iPhone 4s it is 115. iPhone 6+ determines it should be a lot more.
This is the entire code snippet. For testing I have used fixed width rather than the calculated values. The label is set to be the full size of its superview in storyboard. That is why I change the bottom constraint to do the resizing. Any idea why the different devices get different values even when width is set to the same value?
var bounds = UIScreen.mainScreen().bounds
let attrStr = self.infoLabel.attributedText
var width = bounds.width - 40
let size = self.infoLabel.sizeThatFits(CGSizeMake(bounds.width - 40, bounds.height))
let delta = (self.infoLabel.frame.size.height) - size.height
bottomConstaint.constant += delta
Used self.view.bounds rather than UIDevice.mainScreen().bounds, and moved it from viewWillAppear to viewDidLayoutSubviews, and got a perfect result for all devices.