sizeToFit()返回错误的高度 - 需要在heightForRow中找到单元格宽度 [英] sizeToFit() returns wrong height - Need to find cell width in heightForRow

查看:171
本文介绍了sizeToFit()返回错误的高度 - 需要在heightForRow中找到单元格宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试根据内容制作具有动态单元格高度的UITableView。我的应用是文章查看器。我尝试用这些函数计算单元格的高度。

I am trying to make a UITableView with dynamic cell heights, based on the content. My app is an article viewer. I try to calculate the height of the cells with these functions.

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = .ByTruncatingTail
    label.font = font
    label.text = text

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

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    let post = FeedController.sharedController.allPosts[indexPath.row]
    var height = 16.0
    if post.hasImage {
        height += Double(self.view.frame.width) / (4/3)
    }

    let titleH = heightForView(post.title!, font: UIFont(name: "LiberationSerif-Bold", size: 20.0)!, width: self.tableView.bounds.width)
    let descH = heightForView(post.desc!, font: UIFont(name: "LiberationSerif", size: 17.0)!, width: self.tableView.bounds.width)

    let totalHeight = CGFloat(height+Double(titleH)+Double(descH))

    print("imageH: \(height), titleH: \(titleH) detailH: \(descH) totalH:\(totalHeight)")
    return totalHeight
}

当我运行它时,它看起来像这样,你可以看到,底部标签被切断了。

When I run it, it looks like this, as you can see, the bottom label is cut off.

我通过界面断点来运行它,你可以看到错误的原因:

I ran it trough the interface breakpoint thingy, where you can see the cause of the error:

渲染的大小比sizeToFit()的估计大小大一个,正如我从日志语句中看到的那样:

The rendered size is one size larger than the estimated size from sizeToFit(), as you can see from my log statement:

imageH: 297.25, titleH: 44.5 detailH: 56.5 totalH:398.25

我怀疑这个的原因计算错误是由于我提供了具有错误宽度参数的heightForView函数。我曾尝试使用tableView.contentSize和许多其他东西。 lineBreakMode在我的故事板和我的代码中是相同的。

I suspect the reason for this calculation error is due to me providing the heightForView function with the wrong width parameter. I have tried to use tableView.contentSize, and many other things. The lineBreakMode is the same in my storyboard and in my code.

我想我需要的是一种更好的方法来找到单元格的预期宽度,或任何其他能给我正确预期高度的解决方案。

I guess what I need is a better way to find the expected width of the cell, or any other solution which will give me the proper expected height.

编辑:约束:

推荐答案

自动尺寸



代码少得多( *),您可以完全抛弃 heightForRowAtIndexPath ,并使用 autolayout 获取所有内容。

Automatic Dimension

With much less code(*), you can ditch heightForRowAtIndexPath entirely, and use autolayout for everything.


  1. 不要覆盖 heightForRowAtIndexPath (所有代码消失)

  2. 告诉表视图来做艰苦的工作(例如 viewDidLoad ):

  1. Do not overwrite heightForRowAtIndexPath (all that code goes away)
  2. Tell the table view to do the hard work (in viewDidLoad for example):



    self.tableView.estimatedRowHeight = 88
    self.tableView.rowHeight = UITableViewAutomaticDimension

(*) 2行代码,确切地说。
通过比较 2行解决方案针对多种方法覆盖解决方案

(*) 2 lines of code, to be precise. Convince yourself by comparing 2 lines solution against multiple methods override solution.

保证金说明


  • XIB & storyboard :您可以控制约束及其与保证金的关系。

    注意当使用相对于保证金时 ,项目顺序很重要,因为边距通常是插入的。
    有关详细信息,请参见 https://stackoverflow.com/a/25420909/218152

  • XIB & storyboard: you have the ability to control the constraints and their relationships to margin.
    Note that when using Relative to margin, the item order matters, as margins are generally insets. See https://stackoverflow.com/a/25420909/218152 for some details.

storyboard :您可以访问额外的 topLayoutGuide 和来自 IB bottomLayoutGuide 属性,这可能对您的视图控制器有价值,但对于您的 UITableViewCell

storyboard: you have access to the additional topLayoutGuide and bottomLayoutGuide properties from IB, which may be of value for your view controller, but are off-topic for your UITableViewCell.

这篇关于sizeToFit()返回错误的高度 - 需要在heightForRow中找到单元格宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆