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
Figure out size of UILabel based on String in Swift
提问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 attributes
in the extension String
methods
只要改变值attributes
的extension 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
}