UILabel size is not calculated correctly when changing font in UILabel

I am adding UILabel to a view with the following layout requirements:

  • The mark must be centered
  • The label must have a maximum font size of 100 points, but must scale to fit. It should not truncate.
  • The height of the mark must not exceed 450 points.
  • Another view will be located directly below the label.

My label property layout limitations seem to adequately describe this:

let label = UILabel() label.backgroundColor = UIColor.yellowColor() label.font = UIFont.systemFontOfSize(100) label.numberOfLines = 0 label.textAlignment = .Center label.adjustsFontSizeToFitWidth = true label.text = "What Brewing in PET/CT: CT and MR Emphasis" label.setTranslatesAutoresizingMaskIntoConstraints(false) view.addSubview(label) view.addConstraint(NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0)) view.addConstraint(NSLayoutConstraint(item: label, attribute: .Left, relatedBy: .Equal, toItem: view, attribute: .Left, multiplier: 1, constant: 60)) view.addConstraint(NSLayoutConstraint(item: label, attribute: .Right, relatedBy: .Equal, toItem: view, attribute: .Right, multiplier: 1, constant: -60)) view.addConstraint(NSLayoutConstraint(item: label, attribute: .Height, relatedBy: .LessThanOrEqual, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 450)) 

However, I find that with longer content like below, the shortcut appears with some unexpected fields:

enter image description here

This is unacceptable, since any views located directly above or below the label will have a space.

Based on the discussion below, my working theory is that the layout engine calculates a size based on a font size of 100, without taking into account subsequent scaling when the content is larger.

How can I fulfill the layout requirements listed above (ideally without using obsolete methods)?

This is where the test project runs.

+5
source share
2 answers

Take a look at your test project, which you have kindly added.

The problem is that the font you are installing is too large (100pt) and the height of 450 points cannot be satisfied. You set label.adjustsFontSizeToFitWidth = true , which makes it try and paste it as best as possible using a smaller font.

Thus, when you set the font to 100, it determines the size of the text area based on the shortened source text, and then compresses it, changing the font to fit the width. This leaves clearance above and below after compression, as the size was based on the original font.

If you use smaller sizes, such as 90, it works great because it holds less than 450.

If you remove adjustsFontSizeToWith, it works fine and fills the gap, but cuts off the text.

If you remove the height limit, it works fine, but its height goes> 450.

So your problem is that the test font is too large for a height of 450.

Possible Solution:

Ask for the font size label you need using the answer from here: How to get the automatically adjusted font size of UILabel (UITextView)?

You mainly use:

 CGFloat actualFontSize; [label.text sizeWithFont:label.font minFontSize:label.minimumFontSize actualFontSize:&actualFontSize forWidth:label.bounds.size.width lineBreakMode:label.lineBreakMode]; 

This is deprecated, but that does not mean that you cannot use it yet. You need to convert it to fast.

Call this, and if the font size is smaller than the original, set the font in the smaller label. This should theoretically give you the perfect shape, as it should resize the new font size that you installed.

Possible solution update:

I had a search for the quick equivalent of sizeWithFont , and there are many articles, but I did not see what replaced the version of the function mentioned above.

A slightly inefficient solution would be to add the following before your addSubview code to the test project you posted (sorry my quick one). It basically searches back the font size until the font meets known limitations. Obviously, this can be made more efficient, but it shows that if you calculate the correct font before the layout, it will fully correspond to a height of 450.0.

This is tested in your project, and the text is ideal in case it is not suitable for 450.0 from the very beginning.

  // The current font size and name var fontSize:CGFloat = 120 let fontName:String = "AvenirNext-Regular" // The size to fit is the frame width with 60 margin each size and height // of 450 let fitSize:CGSize = CGSize(width:view.frame.width-120.0,height:450) var newSize:CGSize do{ // Create the trial font label.font = UIFont(name: fontName, size: fontSize) // Calculate the size this would need based on the fitSize we want newSize = label.sizeThatFits(fitSize) // Make the font size smaller for next time around. fontSize-=0.5 } while (newSize.height >= 450) println("Font size had to be reduced to \(fontSize)") view.addSubview(label) 
+1
source

I took a look at your project and I may have found a solution to your problem.

I added the following label setting:

 label.minimumScaleFactor = 0.5 

Here is the view after my change: enter image description here

The label is no longer spaced.

Hope this helps you solve your problem! Let me know how it went.

+1
source

All Articles