ios - 在 Swift 中使用多行获取 UILabel 高度

标签 ios swift swift2 uilabel

我正在尝试计算 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 的高度。它返回一个值,但我想这不是真的。我的 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)

提前致谢!

最佳答案

由于您希望在 HTML 内容大于应用程序窗口大小时整个页面都可以滚动,因此我假设您的顶层 View 是 UIScrollView

这里的主要技巧是将显示 HTML 的标签的 height 约束设置为 0 ,然后在计算出它包含的 HTML 文本的高度后以编程方式更新它.

如果显示的文本太长,则 ScrollView 将自动开始滚动,前提是您正确设置了所有垂直约束。

顺便说一句,创建 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 中没有任何 super View 的精确宽度,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下载。 .

关于ios - 在 Swift 中使用多行获取 UILabel 高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39319541/

相关文章:

iphone - iphone 应用程序更新的新私钥和配置文件

ios - Tableview 滚动有点烦躁。我怎样才能让它像黄油一样光滑

swift - 图像不删除为 UIButton 的禁用状态

ios - UILabel:2 行文本收缩

json - 无法将类型 'Swift.Dictionary<Swift.String, protocol<>>' 的值转换为 'Swift.AnyObject'

arrays - 在 Swift 中将字符串缩减为字典

ios - Swift 2 SwiftyJSON API 数据到 UITableView

iOS swift : Load new url to a webview after receiving a push notification

swift - 无法使用 segue 将值从 FirstVC 传递到 SecondVC

ios - Collection View 的复选框无需单击即可执行操作