简体   繁体   中英

Dynamically adjust UILabel frame height after dynamically adjusting the internal text size to fit

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)
    }
}

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

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)
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM