繁体   English   中英

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

[英]Determining the maximum font size for a multi-line UILabel with maximum width

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

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

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

我目前正在部分使用这里找到的解决方案但是它仅在理论上有效。 我不确定为什么,但是当我在“ 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 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
    }

为什么这种方法不起作用,什么是合适的替代方法?

如果我的代码正确,则您正在尝试减小字体大小,直到它适合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
}

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

UPDATE

我没有提到您要确保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循环中使用它来检查它如何变化。

希望对您有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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