1
votes

I am working with an UILabel that is constrained to a fixed width, and no more than a certain height (fixed to, say, half the screen size)

To allow our app to work across iOS devices, I set adjustsfontsizetofitwidth to be true on the UILabel. This leads to a resulting adjustment of the font size of the text if the screen size is small.

However, it appears that if the font is actually resized, the UILabel now has extra top and bottom padding to the text. This is marked as part of its intrinsic content size.

This extra vertical padding is problematic, because I have a button that needs to sit right below the baseline of the last line of text.

I need a method to now readjust my frame to tightly fit the newly adjusted text size.

I tried using sizeToFit() as well as invalidateIntrinsicContentSize in layoutSubviews() for my view class, but to no avail.

It seems similar to this and this, neither of which have answers that work for me.

class ProblemExample: UIViewController {
     private let instructionsLabel: UILabel = {
            let label = UILabel().disableAutoresizingMask()
            label.numberOfLines = 0
            label.text = "Lorem ipsum dolor sit amet, ut adhuc argumentum vix, vix eruditi appetere corrumpit in. Quod cibo mnesarchum ex sea. Ad qui case assum delicata, ei laudem prodesset democritum per, alia admodum efficiantur has id. Semper integre ei est, quo dolor causae definitionem ei. Malis impedit vim at, vero quas sit ea. Quaeque expetenda an est."
            label.font = Theme.headingFont // BIG FONT
            label.setLineSpacing(multiple: 1.15)
            label.textColor = .black
            label.lineBreakMode = .byTruncatingTail
            label.adjustsFontSizeToFitWidth = true;
            label.minimumScaleFactor = 0.5

            return label
        }()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.addSubview(instructionsLabel)
        // Using https://github.com/roberthein/TinyConstraints for syntactical lightness
        instructionsLabel.widthToSuperview(multiplier:0.5)
        instructionsLabel.heightToSuperview(multiplier:0.5, relation:.equalOrLess)
        instructionsLabel.centerYToSuperview()

        button = UIButton()
        self.addSubView()
        button.bottom(to: instructionsLabel)
    }
}

2
if you need dynamic height then dont use this constraint heightToSuperview..... just use left, right, bottom , top constraint you may use width constraint but not height.Abu Ul Hassan
@Winston try "label.lineBreakMode = .wordWrap" then it'll increase the height. Considering you've given all the proper constraints (top, leading, training, bottom) and keeping in mind that top and bottom constraints are not of fix value.Mohit G.
My method to calculate the height of UILabel, stackoverflow.com/a/45182097/419348AechoLiu
@AbuUlHassan I meant heightToSuperview as an less than or equal to constraint.Winston Du

2 Answers

0
votes

You can profit from the built-in behavior when you need either to fit text into the frame, or stretch frame according to the text size. It seems to me, you need both. Hence you have to do it yourself.

The approximate flow would be the following:

  • get the text that you are going to assign to the label
  • calculate the text's height knowing its width (see this)
  • if text height is more than max label height, set label to max height, otherwise set it to text height
  • assign text to label
0
votes

Try by using following code, always add runtime rendering in viewDidLayoutSubViews or after viewDidLayoutSubViews

 override func viewDidLoad() {
        super.viewDidLoad()

    }

 override func viewDidLayoutSubViews(){
        super.viewDidLayoutSubViews()
        self.addSubview(instructionsLabel)
        // Using https://github.com/roberthein/TinyConstraints for syntactical lightness
        instructionsLabel.widthToSuperview(multiplier:0.5)
        instructionsLabel.heightToSuperview(multiplier:0.5, relation:.equalOrLess)
        instructionsLabel.centerYToSuperview()
        if button == nil {
            button = UIButton()
            self.addSubView()
            button.bottom(to: instructionsLabel)
        }
}