确定具有最大宽度的多行UILabel的最大字体大小

时间:2018-09-19 08:31:23

标签: ios swift xcode uikit

现在,我知道有很多问题会问同样的问题,但是大多数问题与多行标签无关,或者答案不起作用或已过时。我看过了。

我试图弄清楚在三行UILabel中显示message所需的最小字体大小,该字体仅占maximumContentWidth的宽度,字体为UIFont.systemFont(.regular)。现在,我意识到UILabel中有一些属性可以使它自动缩小以适合它,但对我不起作用。我需要确定最小字体大小的具体数字,以便将其应用于其他多个UILabel,其中一些显示的文字明显更少。

我的最大字体大小为20,最小字体大小为13。

我目前正在部分使用here找到的解决方案,但是它仅在理论上有效。我不确定为什么,但是当我在“ fa fa fa ...”这样的字符串上做了一些很棒的测试文本时,重复fa直到我从视觉上知道一个fa不能容纳最大字体。但是,对于“ Ww wwwwwwwww wwww wwww www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www www wwwwwww www wwwwwwwwwwwwwww。”系统会完全崩溃,无法使文本变小到所需的大小。

这是探测器

extension UILabel {

    var isTruncated: Bool {

        guard let labelText = text else {
            return false
        }

        let labelTextSize = (labelText as NSString).boundingRect(
            with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
            options: .usesLineFragmentOrigin,
            attributes: [.font: font],
            context: nil).size

        return labelTextSize.height > bounds.size.height
    }
}

这是我的使用方式:

    var testLabel = UILabel()
    var font = 20
    testLabel.numberOfLines = 3
    testLabel.frame.size.width = maximumContentWidth
    while font > 13 {
        testLabel.text = message
        testLabel.font = UIFont.systemFont(ofSize: font, weight: .regular)
        testLabel.sizeToFit()
        if !testLabel.isTruncated {
            break
        }
        font -= 0.1
    }

为什么这种方法不起作用,什么可以替代呢?

1 个答案:

答案 0 :(得分:1)

如果我的代码正确,则您正在尝试减小字体大小,直到它适合UILabel大小。因此,字体大小将尽可能大。

主要问题出在您的while循环中。在每个步骤中,您都需要设置新的font并调用sizeToFit,这会使您更改标签框架以适合字体大小。之后,您的isTruncated将返回false

您需要在每个步骤上手动设置UILabel框架,而不是调用sizeToFit()

testLabel.numberOfLines = 3
testLabel.text = message

while font > 13 {
    testLabel.font = UIFont.systemFont(ofSize: font, weight: .regular)
    testLabel.frame.size = CGSize(width: maximumContentWidth,
                                  height: maximumContentHeight)
    if !testLabel.isTruncated {
        break
    }
    font -= 0.1
}

然后,您将设置所需的标签大小,并检查新字体大小是否使文本适合它。

更新

我没有提到您要确保UILabel的行数不超过3行。这有点棘手,因为没有简单或简单的方法来知道UILabel有多少行。但这就是我在项目中使用的解决方案

extension UILabel {
    func getLinesCount() -> Int {
        let text = self.text ?? ""
        let rectWidth = self.frame.width

        let myFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
        let attStr = NSMutableAttributedString(string: text)
        let range = NSRange(location: 0, length: attStr.length)
        attStr.addAttribute(kCTFontAttributeName as NSAttributedStringKey, value: myFont, range: range)

        let frameSetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString)
        let path: CGMutablePath = CGMutablePath()
        let rect = CGRect(x: 0, y: 0, width: rectWidth, height: CGFloat.greatestFiniteMagnitude)
        path.addRect(rect, transform: .identity)

        let frame: CTFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
        guard let lines = CTFrameGetLines(frame) as? [Any] else { return 0 }
        return lines.count
    }
}

此方法根据标签的fontwidth为标签返回多行。您可以在while循环中使用它来检查它如何变化。

希望它对您有帮助。