ios 在Swift中根据String计算UILabel的大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30450434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:04:41  来源:igfitidea点击:

Figure out size of UILabel based on String in Swift

iosiphonestringswift3uilabel

提问by Cody Weaver

I am trying to calculate the height of a UILabel based on different String lengths.

我正在尝试根据不同的字符串长度计算 UILabel 的高度。

func calculateContentHeight() -> CGFloat{
    var maxLabelSize: CGSize = CGSizeMake(frame.size.width - 48, CGFloat(9999))
    var contentNSString = contentText as NSString
    var expectedLabelSize = contentNSString.boundingRectWithSize(maxLabelSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(16.0)], context: nil)
    print("\(expectedLabelSize)")
    return expectedLabelSize.size.height

}

Above is the current function I use to determine the height but it is not working. I would greatly appreciate any help I can get. I would perfer the answer in Swift and not Objective C.

以上是我用来确定高度的当前函数,但它不起作用。我将不胜感激我能得到的任何帮助。我更喜欢用 Swift 而不是 Objective C 的答案。

回答by Kaan Dedeoglu

Use an extension on String

使用扩展名 String

Swift 3

斯威夫特 3

extension String {
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.height)
    }

    func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.width)
    }
}

and also on NSAttributedString(which is very useful at times)

以及NSAttributedString(有时非常有用)

extension NSAttributedString {
    func height(withConstrainedWidth width: CGFloat) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)

        return ceil(boundingBox.height)
    }

    func width(withConstrainedHeight height: CGFloat) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)

        return ceil(boundingBox.width)
    }
}

Swift 4

斯威夫特 4

Just change the value for attributesin the extension Stringmethods

只要改变值attributesextension String方法

from

[NSFontAttributeName: font]

to

[.font : font]

回答by Sn0wfreeze

For multiline text this answer is not working correctly. You can build a different String extension by using UILabel

对于多行文本,此答案无法正常工作。您可以使用 UILabel 构建不同的 String 扩展

extension String {
func height(constraintedWidth width: CGFloat, font: UIFont) -> CGFloat {
    let label =  UILabel(frame: CGRect(x: 0, y: 0, width: width, height: .greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.text = self
    label.font = font
    label.sizeToFit()

    return label.frame.height
 }
}

The UILabel gets a fixed width and the .numberOfLines is set to 0. By adding the text and calling .sizeToFit() it automatically adjusts to the correct height.

UILabel 获得固定宽度并且 .numberOfLines 设置为 0。通过添加文本并调用 .sizeToFit() 它会自动调整到正确的高度。

Code is written in Swift 3

代码是用 Swift 3 编写的

回答by RyanG

Heres a simple solution thats working for me... similar to some of the others posted, but it doesn't not include the need for calling sizeToFit

这是一个对我有用的简单解决方案......类似于其他一些发布的解决方案,但它不包括调用的需要 sizeToFit

Note this is written in Swift 5

请注意,这是用 Swift 5 编写的

let lbl = UILabel()
lbl.numberOfLines = 0
lbl.font = UIFont.systemFont(ofSize: 12) // make sure you set this correctly 
lbl.text = "My text that may or may not wrap lines..."

let width = 100.0 // the width of the view you are constraint to, keep in mind any applied margins here

let height = lbl.systemLayoutSizeFitting(CGSize(width: width, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel).height

This handles line wrapping and such. Not the most elegant code, but it gets the job done.

这处理换行等。不是最优雅的代码,但它完成了工作。

回答by CrazyPro007

extension String{

    func widthWithConstrainedHeight(_ height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: CGFloat.greatestFiniteMagnitude, height: height)

        let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.width)
    }

    func heightWithConstrainedWidth(_ width: CGFloat, font: UIFont) -> CGFloat? {
        let constraintRect = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.height)
    }

}

回答by iOS

This is my answer in Swift 4.1 and Xcode 9.4.1

这是我在 Swift 4.1 和 Xcode 9.4.1 中的答案

//This is your label
let proNameLbl = UILabel(frame: CGRect(x: 0, y: 20, width: 300, height: height))
proNameLbl.text = "This is your text"
proNameLbl.font = UIFont.systemFont(ofSize: 17)
proNameLbl.numberOfLines = 0
proNameLbl.lineBreakMode = .byWordWrapping
infoView.addSubview(proNameLbl)

//Function to calculate height for label based on text
func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat {
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}

Now you call this function

现在你调用这个函数

//Call this function
let height = heightForView(text: "This is your text", font: UIFont.systemFont(ofSize: 17), width: 300)
print(height)//Output : 41.0

回答by MSimic

I found that the accepted answer worked for a fixed width, but not a fixed height. For a fixed height, it would just increase the width to fit everything on one line, unless there was a line break in the text.

我发现接受的答案适用于固定宽度,但不适用于固定高度。对于固定高度,它只会增加宽度以适应一行中的所有内容,除非文本中有换行符。

The width function calls the height function multiple times, but it is a quick calculation and I didn't notice performance issues using the function in the rows of a UITable.

width 函数多次调用 height 函数,但它是一个快速计算,我没有注意到在 UITable 的行中使用该函数的性能问题。

extension String {

    public func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [.font : font], context: nil)

        return ceil(boundingBox.height)
    }

    public func width(withConstrainedHeight height: CGFloat, font: UIFont, minimumTextWrapWidth:CGFloat) -> CGFloat {

        var textWidth:CGFloat = minimumTextWrapWidth
        let incrementWidth:CGFloat = minimumTextWrapWidth * 0.1
        var textHeight:CGFloat = self.height(withConstrainedWidth: textWidth, font: font)

        //Increase width by 10% of minimumTextWrapWidth until minimum width found that makes the text fit within the specified height
        while textHeight > height {
            textWidth += incrementWidth
            textHeight = self.height(withConstrainedWidth: textWidth, font: font)
        }
        return ceil(textWidth)
    }
}

回答by CSE 1994

Check label text height and it is working on it

检查标签文本高度,它正在处理它

let labelTextSize = ((labelDescription.text)! as NSString).boundingRect(
                with: CGSize(width: labelDescription.frame.width, height: .greatestFiniteMagnitude),
                options: .usesLineFragmentOrigin,
                attributes: [.font: labelDescription.font],
                context: nil).size
            if labelTextSize.height > labelDescription.bounds.height {
                viewMoreOrLess.hide(byHeight: false)
                viewLess.hide(byHeight: false)
            }
            else {
                viewMoreOrLess.hide(byHeight: true)
                viewLess.hide(byHeight: true)

            }

回答by Shanu Singh

This solution will help to calculate the height and width at runtime.

此解决方案将有助于在运行时计算高度和宽度。

    let messageText = "Your Text String"
    let size = CGSize.init(width: 250, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    let estimateFrame = NSString(string: messageText).boundingRect(with:  size, options: options, attributes: [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue", size: 17)!], context: nil)

Here you can calculate the estimated height that your string would take and pass it to the UILabel frame.

在这里,您可以计算字符串的估计高度并将其传递给 UILabel 框架。

estimateFrame.Width
estimateFrame.Height 

回答by George Sabanov

Swift 5:

斯威夫特 5:

If you have UILabel and someway boundingRect isn't working for you (I faced this problem. It always returned 1 line height.) there is an extension to easily calculate label size.

如果你有 UILabel 并且有一种方法 boundingRect 对你不起作用(我遇到了这个问题。它总是返回 1 行高。)有一个扩展可以轻松计算标签大小。

extension UILabel {
    func getSize(constrainedWidth: CGFloat) -> CGSize {
        return systemLayoutSizeFitting(CGSize(width: constrainedWidth, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
    }
}

You can use it like this:

你可以这样使用它:

let label = UILabel()
label.text = "My text\nIs\nAwesome"
let labelSize = label.getSize(constrainedWidth:200.0)

Works for me

为我工作

回答by Niraj Paul

@IBOutlet weak var constraintTxtV: NSLayoutConstraint!
func TextViewDynamicallyIncreaseSize() {
    let contentSize = self.txtVDetails.sizeThatFits(self.txtVDetails.bounds.size)
    let higntcons = contentSize.height
    constraintTxtV.constant = higntcons
}