UITableView

我们都知道UITableView从iOS 8开始实现行高的自适应相对比较简单,首先必须设置estimatedRowHeight给出预估高度,设置rowHeightUITableViewAutomaticDimension(注意:如果不修改rowHeight默认就是UITableViewAutomaticDimension),对于这两个参数除了直接修改tableview对应的属性之外仍然支持使用对应的代理方法设置。最后只要在UITableViewCell中设置contentView的约束即可。由于UITableViewCell的宽度等同于UITableView因此约束的设置事实上只是为了自动计算高度。通常的做法就是设置contentView的top和bottom约束,而后其内部子视图可以提供intrinsicContentSize(例如UIButtonUILabel默认就已经提供)或者已经有明确的height约束。这样一来就可以做到子控件确定了自身高度,而contentView子控件又设置了和contentView相关的bottom约束来反向计算出UITableViewCell的实际高度。

下面仍然以前面UITableView文章的自定义Cell举例,相比之前大量的运算而言Self-Sizing Cells可以说简化了很多。除了设置estimatedRowHeight外最重要的就是添加相关Autolayout约束。由于头像高度已经固定,内容高度可以通过固有高度自动计算,而二者的间隔和top、bottom约束已经固定,从而Self-Sizing Cells可以自动计算出Cell的高度。

高度计算约束关系:



Cell布局代码:

	import UIKit
import SnapKit class StatusTableViewCell: UITableViewCell { // MARK: - 公共属性
var status:Status! {
didSet {
self.avatarImageView.image = UIImage(named: status.profileImageUrl)
self.userNameLabel.text = status.userName
self.mtypeImageView.image = UIImage(named: status.mbtype)
self.createdAtLabel.text = status.createdAt
self.sourceLabel.text = status.source
self.contentLabel.text = status.text
}
} // MARK: - 生命周期及方法覆盖
override func awakeFromNib() {
super.awakeFromNib()
} override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.setup()
} required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
} override func setSelected(_ selected: Bool, animated: Bool) { } // MARK: - 私有方法
private func setup() {
self.contentView.addSubview(self.avatarImageView)
self.contentView.addSubview(self.userNameLabel)
self.contentView.addSubview(self.mtypeImageView)
self.contentView.addSubview(self.createdAtLabel)
self.contentView.addSubview(self.sourceLabel)
self.contentView.addSubview(self.contentLabel) self.avatarImageView.snp.makeConstraints { (make) in
make.top.left.equalTo(10.0)
make.size.equalTo(CGSize(width: 40.0, height: 40.0))
} self.userNameLabel.snp.makeConstraints { (make) in
make.top.equalTo(self.avatarImageView.snp.top)
make.left.equalTo(self.avatarImageView.snp.right).offset(8.0)
} self.mtypeImageView.snp.makeConstraints { (make) in
make.top.equalTo(self.userNameLabel.snp.top)
make.left.equalTo(self.userNameLabel.snp.right).offset(8.0)
make.size.equalTo(CGSize(width: 14.0, height: 14.0))
} self.createdAtLabel.snp.makeConstraints { (make) in
make.left.equalTo(self.userNameLabel.snp.left)
make.bottom.equalTo(self.avatarImageView.snp.bottom)
} self.sourceLabel.snp.makeConstraints { (make) in
make.left.equalTo(self.createdAtLabel.snp.right).offset(10.0)
make.bottom.equalTo(self.createdAtLabel.snp.bottom)
make.right.lessThanOrEqualTo(-8.0)
} self.contentLabel.snp.makeConstraints { (make) in
make.top.equalTo(self.avatarImageView.snp.bottom).offset(8.0)
make.left.equalTo(self.avatarImageView.snp.left)
make.right.equalTo(-8.0)
make.bottom.equalTo(-10.0) // 注意此处必须设置,否则contentView无法自适应高度
} } // MARK: - 私有属性
private lazy var avatarImageView:UIImageView = {
let temp = UIImageView()
return temp
}() private lazy var mtypeImageView:UIImageView = {
let temp = UIImageView()
return temp
}() private lazy var userNameLabel:UILabel = {
let temp = UILabel()
temp.textColor = UIColor(red: 50.0/255.0, green: 50.0/255.0, blue: 50.0/255.0, alpha: 1.0)
temp.font = UIFont.systemFont(ofSize: 14.0)
return temp
}() private lazy var createdAtLabel:UILabel = {
let temp = UILabel()
temp.textColor = UIColor(red: 120.0/255.0, green: 120.0/255.0, blue: 120.0/255.0, alpha: 1.0)
temp.font = UIFont.systemFont(ofSize: 12.0)
return temp
}() private lazy var sourceLabel:UILabel = {
let temp = UILabel()
temp.textColor = UIColor(red: 120.0/255.0, green: 120.0/255.0, blue: 120.0/255.0, alpha: 1.0)
temp.font = UIFont.systemFont(ofSize: 12.0)
return temp
}() private lazy var contentLabel:UILabel = {
let temp = UILabel()
temp.textColor = UIColor(red: 50.0/255.0, green: 50.0/255.0, blue: 50.0/255.0, alpha: 1.0)
temp.font = UIFont.systemFont(ofSize: 14.0)
temp.numberOfLines = 0
return temp
}() }

最终效果:



无论是UITableView还是后面的UICollectionview,Self-Sizing Cells的概念均是从iOS 8开始提出的。如果是iOS 8之前的版本则需要通过systemLayoutSizeFitting()进行计算或者通过frame直接设置。

UICollectionView

了解了UITableView的Cell行高自适应之后,要理解UICollectionviewCell的Size自适应并不难,因为UICollectionViewCell相比较于UITableViewCell除了要通过AutoLayout确定contentView的高度之外还要确定其宽度,其宽度确定原则和UITableViewCell的高度确定是类似的,只是要通过UICollectionviewCell的contentView子控件自身确定其宽度,然后设置子控件和contentView相关的right约束即可。当然对于UICollectionViewCell自适应尺寸同样必须设置UICollectionViewFlowLayout的estimatedItemSize属性(如果使用UICollectionViewFlowLayout)。

下面的的demo演示了类淘宝商品展示的UICollectionview布局,除了通过AutoLayout确定高度外,通过商品图片的left、right约束和width的设置可以反向推断出contentView的宽度,通过Self-Sizing Cells就可以最终确定UICollectionviewCell的size。

Cell布局代码:

	import UIKit

	class ProductCollectionViewCell: UICollectionViewCell {

	    // MARK: - 公共属性
var product:Product! {
didSet {
self.productImageView.image = UIImage(named: product.image)
self.contentLabel.text = product.text
self.priceLabel.text = "¥\(product.price)"
self.salesLabel.text = "\(product.sale)人购买"
}
} // MARK: - 生命周期及方法覆盖
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
} required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
} override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
return super.preferredLayoutAttributesFitting(layoutAttributes)
}
// MARK: - 私有方法
private func setup() {
self.backgroundColor = UIColor.white
self.contentView.addSubview(self.productImageView)
self.contentView.addSubview(self.contentLabel)
self.contentView.addSubview(self.priceLabel)
self.contentView.addSubview(self.salesLabel) let screenWidth = UIScreen.main.bounds.width
self.productImageView.snp.makeConstraints { (make) in
make.top.left.right.equalTo(0.0)
make.height.equalTo(screenWidth*0.5).priority(999)
make.width.equalTo((screenWidth-18)*0.5).priority(999) // 此设置可以确定cell宽度,注意尽管降低了默认的优先级仅仅是为了计算中间步骤不至于约束冲突,最终显示时此约束仍然会生效
} self.contentLabel.snp.makeConstraints { (make) in
make.top.equalTo(self.productImageView.snp.bottom).offset(4.0)
make.left.equalTo(8.0)
make.right.equalTo(-8.0)
make.height.equalTo(28.0)
} self.priceLabel.snp.makeConstraints { (make) in
make.top.equalTo(self.contentLabel.snp.bottom).offset(8.0)
make.left.equalTo(self.contentLabel.snp.left)
make.bottom.equalTo(-8.0) //此设置可以确定cell高度
} self.salesLabel.snp.makeConstraints { (make) in
make.centerY.equalTo(self.priceLabel.snp.centerY)
make.right.equalTo(-8.0)
}
} // MARK: - 私有属性
private lazy var productImageView:UIImageView = {
let temp = UIImageView()
temp.contentMode = .scaleAspectFit
temp.clipsToBounds = true
return temp
}() private lazy var contentLabel:UILabel = {
let temp = UILabel()
temp.textColor = UIColor(red: 50.0/255.0, green: 50.0/255.0, blue: 50.0/255.0, alpha: 1.0)
temp.font = UIFont.systemFont(ofSize: 12.0)
temp.numberOfLines = 2
return temp
}() private lazy var priceLabel:UILabel = {
let temp = UILabel()
temp.textColor = UIColor.orange
temp.font = UIFont.systemFont(ofSize: 14.0)
return temp
}() private lazy var salesLabel:UILabel = {
let temp = UILabel()
temp.textColor = UIColor(red: 150.0/255.0, green: 150.0/255.0, blue: 150.0/255.0, alpha: 1.0)
temp.font = UIFont.systemFont(ofSize: 12.0)
return temp
}() }

最终效果:



除此之外从iOS 8开始,UICollectionViewCell提供了preferredLayoutAttributesFitting()方法用于提供一些cell属性修改,当然通过此方法可以重新修改cell的size(包括Self-Sizing Cells自动计算后的size),对于手动计算高度的情况这也方法也提供了一种不用外部设置cell size的而能提供让UICollectionView确定cell尺寸的方式,但是这并不在Self-Sizing Cells讨论之列,因此本文不再深入讨论。

UITableView、UICollectionView行高/尺寸自适应的更多相关文章

  1. iOS开发tips-UITableView、UICollectionView行高/尺寸自适应

    UITableView 我们都知道UITableView从iOS 8开始实现行高的自适应相对比较简单,首先必须设置estimatedRowHeight给出预估高度,设置rowHeight为UITabl ...

  2. UItableView动态行高 用这两句实现(可以自己计算数据来实现,一般在model中计算)

    // 动态行高 self.tableView.rowHeight = UITableViewAutomaticDimension; // 预估行高 self.tableView.estimatedRo ...

  3. C# 解决EXCEL单元格合并,行高无法自适应问题

    解决方法:根据单元格内容长度,设置单元格所在行的行高 public static float getExcelCellAutoHeight(string strtest, float fontCoun ...

  4. C# 设置Excel数据自适应行高、列宽的2种情况

    Excel表格中,由于各种数据的复杂性,可能存在单元格中的数据字号大小.数据内容长度不一而出现,列宽过宽.过窄或者行高过大.过小的问题.常见的解决方法是调整行高.列宽.在Microsoft Excel ...

  5. UITableView!别再用代码计算行高了(一)

    你还在用代码去计算行高吗?你不感觉那种方式很low吗?从今天起,试着做些改变吧! 别给我讲你喜欢写代码的感觉,你就是要用代码去计算行高,那我这篇文章不适合你. 在讲解复杂内容之前,还是先学习简单的内容 ...

  6. UITableView+FDTemplateLayoutCell计算行高显示<二>

    之前记录过一篇UITableView+FDTemplateLayoutCell计算行高不成功的博客... 传送门:http://www.cnblogs.com/pengsi/p/6571311.htm ...

  7. dataGridView行高自适应

    今天从网上查询相关datagridview行高自适应的信息时,好多都是告诉你直接用下面三行代码: dataGridView1.AutoSizeRowsMode = DataGridViewAutoSi ...

  8. wpf datagrid row height 行高自动计算使每行行高自适应文本

    wpf 的datagrid的行高 要么是Auto,要么是定值:但会带来麻烦就是每行行高都一样. 当需要按内容(主要是wrap 换行的textbox或textblock)来动态调整行高的时候,需要用到d ...

  9. iOS UITableView 解决估算行高和指定行高的矛盾

    喜欢交朋友的加:微信号 dwjluck2013 1.一般来说 在iOS 中若UITableViewCell 固定行高, 会通过 - (CGFloat)tableView:(UITableView *) ...

随机推荐

  1. 一道关于 precision、recall 和 threshold关系的机器学习题

    Suppose you have trained a logistic regression classifier which is outputing hθ(x). Currently, you p ...

  2. ServerSocketChannel

    Java NIO 中的 ServerSocketChannel 是一个可以监听新进来的 TCP 连接的通道, 就像标准 IO 中的 ServerSocket 一样.ServerSocketChanne ...

  3. bzoj4008: [HNOI2015]亚瑟王【期望dp】

    一个特别神奇的dp,特别厉害. f(i, j) 表示 有 j 轮发动技能的牌在 [1, i] 另外的m - j轮在[i + 1, n]之间的概率. 怎么转移呢? 首先考虑i这张牌不选的情况,f(i - ...

  4. IOS开发者证书申请及应用上线发布详解(2014版)

    其实一直以来我都想做一个最齐全的上传应用到appstore的教程,但一直狠不下心,今天凌晨2点12分,我鼓起勇气写教程,来吧不多说.登录开发者中心:http://developer.apple.com ...

  5. javascript---jquery (1事件)

    1.例子说明 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...

  6. 四 APPIUM GUI讲解(Windows版)

    Windows版本的APPIUM GUI有以下图标或者按钮: ·Android Settings  - Android设置按钮,所有和安卓设置的参数都在这个里面 ·General Settings – ...

  7. chrome的功能Copy as cURL

    https://segmentfault.com/q/1010000002508961

  8. shell 远程备份日志

    #!/bin/bash #Function:自动备份给定列表中的目录或文件,并且可以保留N天备份的档案. #可备份至远程主机指定的目录下,但需本机能免密码登录到远程主机,用到ssh-keygen #该 ...

  9. easyui datagrid行中点击a标签链接,行被选中,但是获取不到对应的参数

    easyui中使用比较多的就是datagrid了,表格中添加连接,点击跳转,为比较常用的方式;往往在点及标签后调用getSeleted方法会失效; 一.初始代码: {field: 'id',title ...

  10. 安装 mrtg

    http://blog.csdn.net/cnbird2008/article/details/2072627