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. curl讲解第一篇---入门和基本使用

    概念 它支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP. curl同样支持HTTPS认证,HTTP POST方法, ...

  2. Java面向对象设计

    1.少了程序入口会在输出的地方报这个错: Syntax error, insert "... VariableDeclaratorId" to complete FormalPar ...

  3. 为什么jQuery要返回jQuery.fn.init对象

    作者:zccst jQuery = function( selector, context ) { // The jQuery object is actually just the init con ...

  4. Crazyflie笔记五: CRTP 实时通信协议(一)(转)

    源:Crazyflie笔记五: CRTP 实时通信协议(一) 这里详细介绍了 Crazyflie 的 CRTP实时通信协议的相关内容,由于内容很长,分几篇博文来讲述.这里是第一节内容.欢迎交流:301 ...

  5. Android源码编译jar包BUILD_JAVA_LIBRARY 与BUILD_STATIC_JAVA_LIBRARY的区别(二)

    上文简单介绍了BUILD_JAVA_LIBRARY 与BUILD_STATIC_JAVA_LIBRARY编译出来jar包的区别, 那么你如果拿到了一个内容是dex格式的jar包,而你又偏偏需要这个ja ...

  6. 苹果App Store开发者帐户从申请,验证,到发布应用(2)

    app store付费 上面已经介绍了app store id的注册了,下面在注册基础上,介绍一下app store的付费.   在上面注册成功之后,会收到一封邮件.   1.收到邮件Thank Yo ...

  7. SGU 194 Reactor Cooling ——网络流

    [题目分析] 无源汇上下界可行流. 上下界网络流的问题可以参考这里.↓ http://www.cnblogs.com/kane0526/archive/2013/04/05/3001108.html ...

  8. Memcached源码分析之assoc.c

    #include "memcached.h" #include <sys/stat.h> #include <sys/socket.h> #include ...

  9. Maven的安装环境配置

    一.Maven的安装 二.Maven的配置 Settings.xml可以用来定义本地仓库.远程仓库.联网代理 Settings.xml文件可以存在两个地方: 1.多用户情况 conf目录下 2.单用户 ...

  10. IOS开发-UI学习-使用UIImageView控件制作动画

    先添加40张tomcat的图片到资源列表中:名称为cat_eat0000.jpg到cat_eat0039.jpg. 1.定义所需控件 // 定义按钮,图片控件.可变数组对象 UIButton *act ...