如何在Swift中获取UILabel的高度?

19

我是Swift的初学者,正在尝试获取标签的高度。该标签有多行文本。我想知道它在屏幕上占用的总高度。

(使用Google Translate进行翻译,请参考)


重复问题:http://stackoverflow.com/questions/3484218/uilabel-height - JAL
这取决于您何时检查它。您什么时候检查它? - matt
5个回答

23

使用扩展的 Swift 4

extension UILabel{

public var requiredHeight: CGFloat {
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.attributedText = attributedText
    label.sizeToFit()
    return label.frame.height
  }
}

19

很简单,只需要打电话

label.bounds.size.height

我正在控制台上打印尺寸,但我的标签高度为0.0。这是我尝试的方法:print(label.bounds.size.height) - vb11
你的标签是如何设置的?如果你正在使用自动布局,你需要创建约束条件来给标签一个高度。 - Slayter
1
我有一个垂直堆栈视图,并在其中放置了3个标签。是的,我正在使用自动布局。但是,是否可以在不手动设置高度的情况下获取标签所占用的默认高度呢?@Slayter - vb11
默认高度为0,直到您给它一些约束。 - Slayter
@AhmedR,兄弟,你能否看一下我的问题 https://stackoverflow.com/questions/44966983/how-to-set-label-height-for-auto-adjust-in-read-more-less-with-swift-3 ?谢谢。 - May Phyu
显示剩余2条评论

10

已更新至Swift 3

func estimatedHeightOfLabel(text: String) -> CGFloat {

    let size = CGSize(width: view.frame.width - 16, height: 1000)

    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)

    let attributes = [NSFontAttributeName: UIFont.systemFont(ofSize: 10)]

    let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height

    return rectangleHeight
}

override func viewDidLoad() {
    super.viewDidLoad()

    guard let labelText = label1.text else { return }
    let height = estimatedHeightOfLabel(text: labelText)
    print(height)
}

在此输入图片描述


如果您想使用此方法进行布局,请确保返回ceil(rectangleHeight),否则自动布局可能会裁剪文本。 - productioncoder
@slashburn 你能否详细说明一下,如果我们不使用 return ceil(rectangleHeight) 会出现什么实际问题? - iAj
1
整体方法运行得非常完美。当我在一个较长的UILabel上尝试代码时,文本被裁剪了。因此,我使用了ceil()函数来获取下一个最大的整数,然后内容就不再被裁剪了。 - productioncoder
@slashburn,你说要在使用此方法进行布局时将 rectHeight 强制转换为 ceil,是什么意思?我不明白文本为什么会被裁剪。我将其用在单元格的 sizeForItem 和 sizeForHeader 中。单元格中的 textLabel 有时会换行成2-3行,而其他时候则只有1行,并且没有换行(可能只有2-3个单词而不是一个完整句子)。这两个方法都在单元格显示之前调用,所以我需要使用 return ceil(rectangleHeight) 吗? - Lance Samaria
在我的实验中,我发现如果你将高度指定为95.46875这样的数字,有时自动布局会有困难正确地适应文本。因此,我只是将数字四舍五入。所以95.46875被四舍五入到96,这样我就可以确信没有像素问题,文本将适合其中。不知道这是否是最好的方法,但对我来说有效。 - productioncoder
@slashburn,我忘了感谢你的回复和解释。谢谢! :) - Lance Samaria

3

已测试100%的 Swift 5 ioS 13.2,是在UILabelnumberOfLines = 0时最佳解决方案。

注意:结果被四舍五入。如果您不想要此结果,请删除 ceil() 方法。

如果您想获得高度 -> 将UILabel的Storyboard宽度赋值。

如果您想获得宽度 -> 将UILabel的Storyboard高度赋值。

    let stringValue = ""//your label text
    let width:CGFloat = 0//storybord width of UILabel
    let height:CGFloat = 0//storyboard height of UILabel
    let font = UIFont(name: "HelveticaNeue-Bold", size: 18)//font type and size

    func getLableHeightRuntime() -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = stringValue.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return ceil(boundingBox.height)
    }

    func getLabelWidthRuntime() -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = stringValue.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return ceil(boundingBox.width)
    }

1
它工作得很好,但是当adjustsFontSizeToFitWidth = true时它不起作用。 - Dinesh

1
"

@iajmeri43的答案已更新,适用于Swift 5

"
func estimatedLabelHeight(text: String, width: CGFloat, font: UIFont) -> CGFloat {
    
    let size = CGSize(width: width, height: 1000)
    
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    
    let attributes = [NSAttributedString.Key.font: font]
    
    let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height
    
    return rectangleHeight
}

使用方法如下:

// 1. get the text from the label
guard let theLabelsText = myLabel.text else { return }

// 2. get the width of the view the label is in for example a cell
// Here I'm just stating that the cell is the same exact width of whatever the collection's width is which is usually based on the width of the view that collectionView is in
let widthOfCell = self.collectionView.frame.width

// 3. get the font that your using for the label. For this example the label's font is UIFont.systemFont(ofSize: 17)
let theLabelsFont = UIFont.systemFont(ofSize: 17)

// 4. Plug the 3 values from above into the function
let totalLabelHeight = estimatedLabelHeight(text: theLabelsText, width: widthOfCell, font: theLabelsFont)

// 5. Print out the label's height with decimal values eg. 95.46875
print(totalLabelHeight)

// 6. as @slashburn suggested in the comments, use the ceil() function to round out the totalLabelHeight
let ceilHeight = ceil(totalLabelHeight)

// 7. Print out the ceilHeight rounded off eg. 95.0
print(ceilHeight)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接