如何使多行UILabel文本适合预定义的宽度而不包装中间词

时间:2017-03-19 19:10:32

标签: ios swift interface-builder uilabel

我在Interface Builder中仔细布置了UILabel,并且具有适当的高度和宽度限制。行数设置为4.包装设置为自动换行。文字是" CHECKED"。字体大小非常大,因此它只适合" CHECKE"和" D"在第二行。写作" Checked"而不是" CHECKED"让字体缩小(按预期),以便整个单词适合。但是(文本是用户给定的,并且可以预期用户写入完全大写的单词)具有大写单词,标签不会破坏它/缩小预期的字体。

你对我可能遗漏的内容有什么建议吗?将单词大写(因此只有第一个字母大写)确实有效,但不是客户想要的。

更新了问题

问题似乎与大写或小写文本无关。我的问题可以通过回答以下问题来解决:

如何制作(理想情况下仅在Interface Builder的帮助下)UILabel文本缩小,试图在所有可用行中包含完整单词而不用包装文本中间词?

  • 如果文字" CHECKED"对于标签而言太宽(有超过1行可用)它应该缩小字体大小而不是打破" D"并将单个字母包装到下一行。
  • 如果文字是"一个CHECKED两个"和单词" CHECKED"对于一个标签已经太宽了(有超过1行可用),它应该在所有单词缩小字体大小之间中断,以便" CHECKED"仍然适合中线。

避免:

one
CHECKE
D two

非常感谢!

3 个答案:

答案 0 :(得分:1)

这是一个 UILabel 子类,它会找到标签 text 中最大的单词,使用 boundingRectNSString 函数来查看这个单词有多大使用当前字体,然后减小字体大小直到适合宽度。

class AutosizingMultilineLabel: UILabel {
    override func layoutSubviews() {
        super.layoutSubviews()
        self.adjustFontToFitWidth()
    }
    
    func adjustFontToFitWidth() {
        guard let currentFont = self.font else { return }
        let minimumFontSize: CGFloat = floor(self.minimumScaleFactor * currentFont.pointSize)
        
        var newFontSize = currentFont.pointSize
        var theNewFont = currentFont
        
        if let text = self.text, let longestWord = text.components(separatedBy: " ").max(by: {$1.count > $0.count})?.replacingOccurrences(of: "\n", with: "") {
            let nsString = longestWord as NSString
            
            while newFontSize > minimumFontSize {
                theNewFont = currentFont.withSize(newFontSize)
                
                let boundingRect = nsString.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude),
                                                         options: NSStringDrawingOptions.usesLineFragmentOrigin,
                                                         attributes: [.font: theNewFont],
                                                         context: nil)
                
                if ceil(boundingRect.size.width) <= self.bounds.size.width {
                    break
                }
                newFontSize -= 1
            }
            
            self.font = theNewFont
        }
    }
}

答案 1 :(得分:0)

当单词大于该行时,自动换行不起作用。如果它不适合这一行,它将不适合下一行。 (相同的单词,相同的大小,相同的行大小)。为了使其合适,标签将开始在下一行放置字母。

如果标签上有多行,操作系统会在调整字体大小之前尝试填充行。

答案 2 :(得分:0)

我认为你只是遇到了自动收缩的限制。

在Interface Builder中:

  • 使用UILabelWidth: 230
  • 添加新的Height: 280
  • 将字体设置为System 44.0
  • 设置Line Break: Truncate Tail
  • Autoshrink: Minimum Font Scale
  • 设置0.15
  • 将标签文字设为test CHECKED lines

现在,左右拖动标签右边缘的手柄......当它太窄时,单词CHECKED将会突破到下一行。

CHECKED更改为checked并执行相同的操作。你应该看到同样的行为。

现在,尝试上下拖动底部边缘。对于CHECKEDchecked,您应该看到字体大小自动缩小。

所以......要做你想做的事情,你可能必须跳过自动收缩,而是做一些代码计算。

编辑:进一步了解发生的事情...

  • 从上面的值开始,但将标签的Height设置为170 - 只给它一点垂直填充。
  • 现在,拖动左边缘使其变窄。
  • 当你到达单词CHECKED的末尾并继续前进时,你会看到字体缩小,直到它变得足够小,以至于它有空间包裹到第4行。

我认为您需要一些代码来准确获取所需内容。