ios - 动态设置 .left 和 .justified 之间的 UILabel 文本对齐方式

标签 ios swift uikit uilabel

在我的应用程序中,我有一个预设有两行的 UILabel 。我可以将文本对齐方式设置为 .left.justified

如果我将其设置为 .left,如果一行中的最后一个单词与标签的最大 x 位置之间有足够的空间,则不会出现布局问题。然而,当没有那么多空间时,最后一个单词非常接近最大 x 位置,它看起来有点奇怪,因为它并不完全右对齐(就像 .justified.

如果我将其设置为.justified,它总是对齐得很好,但有时各个字符之间的距离看起来很奇怪。

我正在寻找一种根据第一行最后一个单词到标签最大 x 位置之间的距离动态调整文本对齐方式的方法。比如说,如果最后一个单词的最后一个字符的位置小于 50,我想要文本对齐 .left,否则我想要 .justified 。有什么办法可以实现这一点吗?

最佳答案

我采取了一种相当老套的方法,需要一些处理能力,但它似乎有效。

<小时/>

首先,我使用此扩展获取标签第一行中的字符串:

import CoreText

extension UILabel {

   /// Returns the String displayed in the first line of the UILabel or "" if text or font is missing
   var firstLineString: String {

    guard let text = self.text else { return "" }
    guard let font = self.font else { return "" }
    let rect = self.frame

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

    let frameSetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString)
    let path = CGMutablePath()
    path.addRect(CGRect(x: 0, y: 0, width: rect.size.width + 7, height: 100))
    let frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)

    guard let line = (CTFrameGetLines(frame) as! [CTLine]).first else { return "" }
    let lineString = text[text.startIndex...text.index(text.startIndex, offsetBy: CTLineGetStringRange(line).length-2)]

    return lineString
  }
}

之后,我计算宽度,使用此扩展的该字符串需要一个行号为 1 且固定高度的标签:

extension UILabel {

   /// Get required width for a UILabel depending on its text content and font configuration
   class func calculateWidth(text: String, height: CGFloat, font: UIFont) -> CGFloat {

       let label = UILabel(frame: CGRect(x: 0, y: 0, width: CGFloat.greatestFiniteMagnitude, height: height))
       label.numberOfLines = 1
       label.font = font
       label.text = text
       label.sizeToFit()

       return label.frame.size.width
   }
}

据此,我可以计算到右侧的距离,并决定是否选择文本对齐.left.justified,所以主要代码如下所示:

// Set text
myLabel.text = someString

// Change text alignment depending on distance to right
let firstLineString = myLabel.firstLineString
let distanceToRight = myLabel.frame.size.width - UILabel.calculateWidth(text: firstLineString, height: myLabel.frame.size.height, font: myLabel.font)
myLabel.textAlignment = distanceToRight < 20 ? .justified : .left

关于ios - 动态设置 .left 和 .justified 之间的 UILabel 文本对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40428504/

相关文章:

ios - TableView不符合协议(protocol)

ios - Playground 上选定设备错误的运行时

ios - 如何以编程方式检查 iPhone 中可用的 3D Touch?

ios - 为什么 Realm 在查询 `size == 4` 时抛出异常?

ios - 如何改变 UIPickerView 的高度

ios - 按钮在其 super View 自动居中时不起作用

ios - 按位非运算符 (~) 不适用于 SWIFT 1.2 中的 bool 值

swift - 尝试使用 spritekit 和 swift 更改触摸时的对象位置

ios - 跑卫登录

swift - 对 swift 中的类型判断感到困惑?