博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Auto Layout 使用心得(五)—— 根据文字、图片自动计算 UITableViewCell 高度
阅读量:7071 次
发布时间:2019-06-28

本文共 4730 字,大约阅读时间需要 15 分钟。


原文发表在我的个人网站:


此系列文章代码仓库在 ,有不明白的地方可以参考我的 Auto Layout 设置哦,下载到本地打开就可以了。

简介

本文中,我们将一起使用 Auto Layout 技术,让 UITableViewCell 的高度随其内部的 UILabel 和 UIImageView 的内容自动变化。

搭建界面

恢复之前删除的按钮

放置一个按钮,恢复到 firstTableViewController 的连接:

pic

别忘了添加约束让他居中哦。

修改 firstTableViewCell

将 firstTableViewCell 的尺寸设置为 600 * 81,将 logo 的尺寸设置为 80 * 80。将 logo 的约束修改为如下图所示:

pic

修改 label 的尺寸和位置,添加约束如下图:

pic

给 ViewController 增加 UINavigationController 嵌套

为了便于返回。操作如下图:

pic

查看结果

pic

根据 label 自动计算 firstTableViewCell 高度

选中 label,设置 lines 行数为 0,表示不限长度自动折行:

pic

修改 label 的文字内容让其超出一行:

swiftimport UIKitclass firstTableViewController: UITableViewController {    var labelArray = Array
() // 用于存储 label 文字内容 override func viewDidLoad() { super.viewDidLoad() var nib = UINib(nibName: "firstTableViewCell", bundle: nil) self.tableView.registerNib(nib, forCellReuseIdentifier: "firstTableViewCell") // 循环生成 label 文字内容 for i in 1...10 { var text = "" for j in 1...i { text += "Auto Layout" } labelArray.append(text) } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // MARK: - Table view data source override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return 50 } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return labelArray.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("firstTableViewCell", forIndexPath: indexPath) as! firstTableViewCell cell.firstLabel.text = labelArray[indexPath.row] return cell }}

现在到了最关键的时刻,驱动 UITableViewCell 适应 Label 内容:

1. 使用 estimatedHeightForRowAtIndexPath 替代 heightForRowAtIndexPath

estimatedHeightForRowAtIndexPath 是 iOS 7 推出的新 API。如果列表行数有一万行,那么 heightForRowAtIndexPath 就会在列表显示之前计算一万次,而 estimatedHeightForRowAtIndexPath 只会计算当前屏幕中显示着的几行,会大大提高数据量很大时候的性能。

2. 新建一个 prototypeCell 成员变量以复用,并在 viewDidLoad 中初始化
swiftclass firstTableViewController: UITableViewController {    var labelArray = Array
() // 用于存储 label 文字内容 var prototypeCell: firstTableViewCell! override func viewDidLoad() { super.viewDidLoad() var nib = UINib(nibName: "firstTableViewCell", bundle: nil) self.tableView.registerNib(nib, forCellReuseIdentifier: "firstTableViewCell") // 初始化 prototypeCell 以便复用 prototypeCell = tableView.dequeueReusableCellWithIdentifier("firstTableViewCell") as! firstTableViewCell......
3. 计算出高度
swiftoverride func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {    let cell = prototypeCell    cell.firstLabel.text = labelArray[indexPath.row]    return cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1}
4. 查看效果

pic

超级大坑

上面让 firstTableViewCell 根据 label 自动计算高度的过程中,有一个超级大坑:如果给左侧 UIImageView 赋的图片较大(大于 80px),将看到如下奇怪的结果:

pic

这只是因为图片把 UITableViewCell 撑大了,并不是我们的计算没有效果。

解决大坑:进攻是最好的防守!根据图片自动计算 firstTableViewCell 高度

首先,把图片的渲染模式改成 Aspect Fit:

pic

给 Images.xcassets 增加三张图片,命名为 0、1、2,尺寸从小到大:

pic

给 cellForRowAtIndexPath 增加代码:

swiftif indexPath.row < 3 {    cell.logoImageView.image = UIImage(named: indexPath.row.description)}

查看效果:

pic

前两个 cell 看起来比较正常,第三个为什么多出了那么多空白?这就是使用 Auto Layout 限制图片宽度为 80px 的原生问题:宽度虽然限制了,高度却依然是原图的高度。解决办法也很简单:如果图片宽度大于 80px,就重绘一张 80px 宽度的图片填充进去。

新建一个 Group(虚拟文件夹),叫 Extensions,并在其内部新建 UIImage.swift 文件,内容如下:

swiftimport UIKitextension UIImage {    func resizeToSize(size: CGSize) -> UIImage {        UIGraphicsBeginImageContext(size)        self.drawInRect(CGRectMake(0, 0, size.width, size.height))        let newImage = UIGraphicsGetImageFromCurrentImageContext()        UIGraphicsEndImageContext()        return newImage    }}

给 UIImage 类扩展了一个名为 resizeToSize 的方法,返回一个按照要求的大小重绘过的 UIImage 对象。修改 cellForRowAtIndexPath 的代码为:

swiftoverride func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {    let cell = tableView.dequeueReusableCellWithIdentifier("firstTableViewCell", forIndexPath: indexPath) as! firstTableViewCell    cell.firstLabel.text = labelArray[indexPath.row]    if indexPath.row < 3 {        var image = UIImage(named: indexPath.row.description)!        if image.size.width > 80 {            image = image.resizeToSize(CGSizeMake(80, image.size.height * (80 / image.size.width)))        }        cell.logoImageView.image = image    }    return cell}

搞定!

查看效果

pic

从上图可以看出,cell 已经可以根据图片和文字中比较高的一个完全自适应。

致谢

感谢 ,给我提供了许多基础知识和灵感。

下一步:

转载地址:http://cbell.baihongyu.com/

你可能感兴趣的文章
CSS3动画卡顿性能优化解决方案
查看>>
阿北的知识分享小程序中restful使用经验贴
查看>>
[WUST2017]一组简单一点的题目(一)W - Digital Roots
查看>>
FrameWork
查看>>
前端每周清单第 16 期:JavaScript 模块化现状;Node V8 与V6 真实性能对比
查看>>
敏捷公关
查看>>
可信云认证累计达20项,腾讯云技术创新能力再获专业认可
查看>>
一文看懂大数据领域的六年巨变
查看>>
《The Startup Way》作者访谈
查看>>
Spring Boot 2.2首个里程碑版本发布,改进性能和内存使用
查看>>
访谈:当开发者成为技术主管 如何领导团队
查看>>
Google发布App Engine第二代运行时,提供Python 3.7和PHP 7.2支持
查看>>
安全狗:云时代的服务器安全守护者
查看>>
从初创型到独角兽企业,监控架构演进的那些事儿
查看>>
BAT集体升级云事业部,这背后都藏着哪些“小心思”?
查看>>
Oracle 裁员史:技术人死于重组,卒于云计算
查看>>
GNU parallel 笔记
查看>>
性能之巅:Linux网络性能分析工具
查看>>
InfoQ就Spring Boot 2.0 GA版发布采访了项目牵头人Phil Webb
查看>>
Oracle回应用户锁定,自治数据库是更好选择
查看>>