How to check current font size of UILabel?

一曲冷凌霜 提交于 2020-01-30 08:08:10

问题


I have 3 UILabels and I want to set same (the smallest one from all of 3 possibilities) font for all of them. What is the problem? I don't know how to check the current font - each of UILabels use Autoshrink with minimal font scale and lines amount equaled to 0. The text of UILabels is set in ViewDidLoad() method (there are many combinations of possible label texts).

I tried to get the current font size with UILabel.font.pointSize property (called in viewDidAppear() method) and than compare all of them. The problem is that that UILabel.font.pointSize returns not current value of UILabel text font size (after Autoshrink has been done) but the value that is set in storyboard.

I'm totally out of ideas so thanks for the help!

Greetings, John


回答1:


This is one way to get the current size of the UILabel pointsize although I know of more ways if this does not work. This is the cleanest and fastest. See example and extension included.

import UIKit

class ViewController: UIViewController {

    lazy var label1 : UILabel = {
        let lbl = UILabel(frame: CGRect(x: 20, y: 80, width: self.view.bounds.width - 40, height: 40))
        lbl.text = "This is some large text to make it fit to size with a big font size"
        lbl.font = UIFont.systemFont(ofSize: 50, weight: .bold)
        lbl.textColor = .black
        lbl.minimumScaleFactor = 0.01
        lbl.adjustsFontSizeToFitWidth = true
        lbl.numberOfLines = 0
        return lbl
    }()

    lazy var label2 : UILabel = {
        let lbl = UILabel(frame: CGRect(x: 20, y: label1.frame.maxY + 5, width: self.view.bounds.width - 40, height: 40))
        lbl.text = "This is one line"
        lbl.font = UIFont.systemFont(ofSize: 20, weight: .bold)
        lbl.textColor = .black
        lbl.minimumScaleFactor = 0.01
        lbl.adjustsFontSizeToFitWidth = true
        lbl.numberOfLines = 0
        return lbl
    }()

    lazy var label3 : UILabel = {
        let lbl = UILabel(frame: CGRect(x: 20, y: label2.frame.maxY + 10, width: self.view.bounds.width - 40, height: 80))
        lbl.text = "This is some large text to make it fit to size with a big font size"
        lbl.font = UIFont.systemFont(ofSize: 100, weight: .bold)
        lbl.textColor = .black
        lbl.minimumScaleFactor = 0.01
        lbl.adjustsFontSizeToFitWidth = true
        lbl.numberOfLines = 0
        return lbl
    }()


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.addSubview(label1)
        self.view.addSubview(label2)
        self.view.addSubview(label3)

        var minSize : CGFloat = .greatestFiniteMagnitude
        for sub in self.view.subviews{
            if let lbl = sub as? UILabel{
                //get the size
                let font = lbl.adjustedFont()
                print("the size is \(font.pointSize)")
                minSize = min(font.pointSize,minSize)
            }
        }
        print("the minimum for all fonts is \(minSize)")
        print("i am going to delay for 3 seconds and then reset all the labels to the minimum size :)")
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) {
            for sub in self.view.subviews{
                if let lbl = sub as? UILabel{
                    lbl.font = lbl.font.withSize(minSize)
                }
            }
        }
    }
}
extension UILabel{
    func adjustedFont()->UIFont {
        guard let txt = text else {
            return self.font
        }
        let attributes: [NSAttributedString.Key: Any] = [.font: self.font]
        let attributedString = NSAttributedString(string: txt, attributes: attributes)
        let drawingContext = NSStringDrawingContext()
        drawingContext.minimumScaleFactor = self.minimumScaleFactor
        attributedString.boundingRect(with: bounds.size,
                                      options: [.usesLineFragmentOrigin,.usesFontLeading],
                                      context: drawingContext)

        let fontSize = font.pointSize * drawingContext.actualScaleFactor
        return font.withSize(CGFloat(floor(Double(fontSize))))
    }
}

Example in Action




回答2:


What I've found is that inside viewDidLoad() your constraints are not fully defined yet. You can try to do these calculations in another method for example viewWillAppear() or any other that suits you and is executed after viewDidLoad().




回答3:


use this extention

extension String {

       func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
            let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
            let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

            return ceil(boundingBox.height)
        }
}

get height

height = strDesc.height(withConstrainedWidth: UIScreen.main.bounds.size.width - 160, font: UIFont.systemFont(ofSize: 14.0))


来源:https://stackoverflow.com/questions/52929271/how-to-check-current-font-size-of-uilabel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!