最终效果

方式1:在cell的数据model中,用boundingRect手动计算
以常见的评论cell为例
comment.swift
let DefaultHeadHeight: CGFloat = 50 //用户头像图片尺寸
let DefaultMargin15: CGFloat = 15 //label 和 头像间距
let DefaultMargin20: CGFloat = 20
// 行高, 计算性属性, 只读
var rowHeight : CGFloat{
let contentWidth = ScreenWidth - DefaultMargin15 - DefaultMargin20 - DefaultHeadHeight
let contentHeight = (content! as NSString).boundingRectWithSize(CGSizeMake(contentWidth, CGFloat.max),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName : UIFont.systemFontOfSize(12)],
context: nil).size.height
return DefaultMargin10 + DefaultHeadHeight + contentHeight + DefaultMargin10 + 30 + DefaultMargin10
}
使用
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return comments![indexPath.row].rowHeight
}
这种方式使用简单灵活,但精确度不高,效率也不高,cell复用一次就要计算一次
方式2:autoLayout+estimatedRowHeight
使用
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
这种方式最常用,但要注意cell的layout要完善,不然起不到作用。
约束要点:让cell的子视图与contentView之间产生垂直的连结,让它们能够对contentView“施加压力”,使contentView扩展以适合它们的尺寸。【如下图】

方式3:与方式2相似,但能提高效率
使用
// 存放复用的cell
private var offscreenCells = [String: CommentCell]()
// 自动计算
tableView.estimatedRowHeight = 100
// 返回计算得到的真实的高度
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = offscreenCells[reuseId] //let reuseId = "CommentCell"
if cell == nil {
cell = CommentCell(style: .Default, reuseIdentifier: reuseId)
offscreenCells[reuseId] = cell
}
// 确保cell的布局约束被设置好了,因为它可能刚刚才被创建好。
// 使用下面两行代码,前提是假设你已经在cell的updateConstraints方法中设置好了约束:
cell?.setNeedsUpdateConstraints()
cell?.layoutIfNeeded()
cell?.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell!.bounds));
// 触发cell的布局过程,会基于布局约束计算所有视图的frame。
// (注意,你必须要在cell的-[layoutSubviews]方法中给多行的UILabel设置好preferredMaxLayoutWidth值;或者在下面2行代码前手动设置!)
cell?.setNeedsLayout()
cell?.layoutIfNeeded()
// 得到cell的contentView需要的真实高度
let height = cell!.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
return height + 1 // +1是分割线的高度
}
这种方式效率高,但使用复杂,一般情况下不推荐使用,推荐简单点的第二种,但一定要练好自己的autoLayout能力。
附一篇参考文章
!(使用Autolayout实现UITableView的Cell动态布局和高度动态改变)(http://blog.163.com/china_uv/blog/static/1171372672014111681232340/)
网友评论