在 Swift 中获取多行的 UILabel 高度
Getting UILabel height with multiple lines in Swift
我正在尝试计算 UILabel 的高度以使页面可滚动。标签包含 attributedText 以显示 HTML 内容。
我正在使用此函数将我的 HTML 内容添加到 UILabel:
func stringFromHTML( string: String?) -> NSAttributedString
{
do{
let pStyle = NSMutableParagraphStyle()
pStyle.lineSpacing = 4
pStyle.paragraphSpacingBefore = 10
let str = try NSMutableAttributedString(data:string!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true
)!, options:[NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSNumber(unsignedLong: NSUTF8StringEncoding)], documentAttributes: nil)
str.addAttribute(NSParagraphStyleAttributeName, value: pStyle, range: NSMakeRange(0, str.length))
str.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica Neue", size: 16.0)!, range: NSMakeRange(0, str.length))
return str
} catch
{
print("html error\n",error)
}
return NSAttributedString(string: "")
}
我是新手。所以,我进行了研究并找到了这个扩展来获得 UILabel 的高度。它 returns 是一个值,但我想这不是真的。我的 UIScrollView 似乎不起作用:
extension UILabel{
func requiredHeight() -> CGFloat{
let label:UILabel = UILabel(frame: CGRectMake(0, 0, self.frame.width, CGFloat.max))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
label.font = self.font
label.text = self.text
label.sizeToFit()
return label.frame.height
}
}
这是我在 viewDidLoad() 方法中用于约束的代码:
// Set ContentView height
let activityTitleHeight:CGFloat = self.activityTitle.requiredHeight() + 20
let activityDescHeight:CGFloat = self.activityDesc.requiredHeight() + 20
let totalContentHeight:CGFloat = activityDescHeight + activityTitleHeight + 345
// There is an image view and a navigation, their total height: 345
let contentViewHeight:NSLayoutConstraint = NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: totalContentHeight)
self.contentView.addConstraint(contentViewHeight)
提前致谢!
将这样的文本放入 UITextView 是更好的方法。此元素用作文本容器:
- 多行支持
- 归因支持
- 无论文本的长度如何,它都适合视图,因为它像滚动视图一样工作
.
let textField = UITextField()
textField.text = "Your long text from HTML source ..."
textField.frame = CGRect(x: 0, y: 0, width: 375, height: 200)
self.contentView.addSubview(textField)
即使你不使用故事板,我post只是一个小截图,这个UI元素带来了什么属性。
由于您希望在 HTML 内容大于应用程序 window 的大小时整个页面变为可滚动,因此我假设您的顶级视图是 UIScrollView
.
这里的主要技巧是将显示 HTML 的标签的 height 约束设置为 0
,然后在计算高度后以编程方式更新它它包含的 HTML 文本。
如果显示的文本太长,滚动视图将自动开始滚动,前提是您正确设置了所有垂直约束。
顺便说一句,创建 UILabel
只是为了计算字符串的高度是一种矫枉过正。自 iOS7 起,我们有 NSAttributedString.boundingRect(size:options:context)
方法计算绘制具有给定选项的文本所需的最小矩形:
string.boundingRectWithSize(CGSizeMake(width, CGFloat.max), options: [.UsesFontLeading, .UsesLineFragmentOrigin], context: nil)
回到你的问题,你应该创建一个 NSLayoutConstraint
类型的 ivar 代表相关标签的高度:
class ViewController: UIViewController {
@IBOutlet weak var htmlLabel: UILabel!
private var labelHeightConstraint: NSLayoutConstraint!
...
并将其 constant
属性 设置为 0
正如我们之前所说:
override func viewDidLoad() {
super.viewDidLoad()
...
htmlLabel.text = stringFromHTML(htmlText)
labelHeightConstraint = NSLayoutConstraint(item: htmlLabel, attribute: .Height, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 0, constant: 0)
scrollView.addConstraint(labelHeightConstraint)
}
然后计算标签的高度:
(因为我们没有 viewDidLoad
中任何超级视图的 精确 宽度,viewDidAppear
是一个很好的地方做这样的计算。)
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let maxSize = CGSizeMake(CGRectGetWidth(scrollView.frame), CGFloat.max)
let textSize = htmlLabel.attributedText!.boundingRectWithSize(maxSize, options: [.UsesFontLeading, .UsesLineFragmentOrigin], context: nil)
labelHeightConstraint.constant = ceil(textSize.height)
}
我为您创建了一个测试项目来展示我上面所做的。您可以从 here.
下载
我正在尝试计算 UILabel 的高度以使页面可滚动。标签包含 attributedText 以显示 HTML 内容。
我正在使用此函数将我的 HTML 内容添加到 UILabel:
func stringFromHTML( string: String?) -> NSAttributedString
{
do{
let pStyle = NSMutableParagraphStyle()
pStyle.lineSpacing = 4
pStyle.paragraphSpacingBefore = 10
let str = try NSMutableAttributedString(data:string!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true
)!, options:[NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSNumber(unsignedLong: NSUTF8StringEncoding)], documentAttributes: nil)
str.addAttribute(NSParagraphStyleAttributeName, value: pStyle, range: NSMakeRange(0, str.length))
str.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica Neue", size: 16.0)!, range: NSMakeRange(0, str.length))
return str
} catch
{
print("html error\n",error)
}
return NSAttributedString(string: "")
}
我是新手。所以,我进行了研究并找到了这个扩展来获得 UILabel 的高度。它 returns 是一个值,但我想这不是真的。我的 UIScrollView 似乎不起作用:
extension UILabel{
func requiredHeight() -> CGFloat{
let label:UILabel = UILabel(frame: CGRectMake(0, 0, self.frame.width, CGFloat.max))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
label.font = self.font
label.text = self.text
label.sizeToFit()
return label.frame.height
}
}
这是我在 viewDidLoad() 方法中用于约束的代码:
// Set ContentView height
let activityTitleHeight:CGFloat = self.activityTitle.requiredHeight() + 20
let activityDescHeight:CGFloat = self.activityDesc.requiredHeight() + 20
let totalContentHeight:CGFloat = activityDescHeight + activityTitleHeight + 345
// There is an image view and a navigation, their total height: 345
let contentViewHeight:NSLayoutConstraint = NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: totalContentHeight)
self.contentView.addConstraint(contentViewHeight)
提前致谢!
将这样的文本放入 UITextView 是更好的方法。此元素用作文本容器:
- 多行支持
- 归因支持
- 无论文本的长度如何,它都适合视图,因为它像滚动视图一样工作
.
let textField = UITextField()
textField.text = "Your long text from HTML source ..."
textField.frame = CGRect(x: 0, y: 0, width: 375, height: 200)
self.contentView.addSubview(textField)
即使你不使用故事板,我post只是一个小截图,这个UI元素带来了什么属性。
由于您希望在 HTML 内容大于应用程序 window 的大小时整个页面变为可滚动,因此我假设您的顶级视图是 UIScrollView
.
这里的主要技巧是将显示 HTML 的标签的 height 约束设置为 0
,然后在计算高度后以编程方式更新它它包含的 HTML 文本。
如果显示的文本太长,滚动视图将自动开始滚动,前提是您正确设置了所有垂直约束。
顺便说一句,创建 UILabel
只是为了计算字符串的高度是一种矫枉过正。自 iOS7 起,我们有 NSAttributedString.boundingRect(size:options:context)
方法计算绘制具有给定选项的文本所需的最小矩形:
string.boundingRectWithSize(CGSizeMake(width, CGFloat.max), options: [.UsesFontLeading, .UsesLineFragmentOrigin], context: nil)
回到你的问题,你应该创建一个 NSLayoutConstraint
类型的 ivar 代表相关标签的高度:
class ViewController: UIViewController {
@IBOutlet weak var htmlLabel: UILabel!
private var labelHeightConstraint: NSLayoutConstraint!
...
并将其 constant
属性 设置为 0
正如我们之前所说:
override func viewDidLoad() {
super.viewDidLoad()
...
htmlLabel.text = stringFromHTML(htmlText)
labelHeightConstraint = NSLayoutConstraint(item: htmlLabel, attribute: .Height, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 0, constant: 0)
scrollView.addConstraint(labelHeightConstraint)
}
然后计算标签的高度:
(因为我们没有 viewDidLoad
中任何超级视图的 精确 宽度,viewDidAppear
是一个很好的地方做这样的计算。)
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let maxSize = CGSizeMake(CGRectGetWidth(scrollView.frame), CGFloat.max)
let textSize = htmlLabel.attributedText!.boundingRectWithSize(maxSize, options: [.UsesFontLeading, .UsesLineFragmentOrigin], context: nil)
labelHeightConstraint.constant = ceil(textSize.height)
}
我为您创建了一个测试项目来展示我上面所做的。您可以从 here.
下载