UITableViewCell高度自适应探索--UITableView+FDTemplateLayoutCell
地址: http://www.jianshu.com/p/7839e3a273a6
UITableViewCell高度自适应探索--cell预估高度(一)
地址: http://www.jianshu.com/p/6ab92579fcf1
UITableViewCell高度自适应探索--cell预估高度(二)
地址: http://www.jianshu.com/p/f3609cd9392e
今天,再提供一种AutoLayout与Frame相结合的方式来设置cell高度的方法.

今天这个方法的要点是:

  • 使用Autolayout在进行布局.
  • 使用Frame进行高度计算
  • 使用模型的属性缓存每个Cell第一次计算的高度.

相对于之前说的那些方法,这个方法比UITableView+FDTemplateLayoutCell使用起来更简单和容易理解(自从写FD那篇文章发表后收到很多网友的关于使用的问题,大部分是由于没有使用正确);并且克服了预估高度方式的那些问题,也不用把约束改来改去, 使计算的过程更加可控.

这种方法虽然是使用fram的方式计算,但是如果没有autoLayout,计算的过程就会复杂几倍,有时候可能还需要一个专门的类去管理子控件的frame.在我看来是一个比较不错的方法.

进入正题.

先看要实现的效果:

目标效果

其中文字的长度不一,图片可能有或没有.为了排除其他干扰,数据来自plist文件.

  • 这是我们自定义cell的设置,这些元素是固定的,我们使用AutoLayout对它们几个进行布局.

cell布局
  • 创建一个Message模型,赋予其对应的属性.
    由于cell的高度本质上还是基于模型数据来算的,所以计算高度的任务交给模型,故模型同时开放一个cellHeight的只读属性,将来好拿给控制器使用.
 @interface Message : NSObject

 // 头像、名字、和描述文字我给固定了,所以没有弄属性处理
@property (nonatomic, copy) NSString *imageName;
@property (nonatomic, copy) NSString *content;
@property (nonatomic, assign, readonly) CGFloat cellHeight; @end
  • 模型计算Cell高度,通过重写cellHeight的getter方法实现
 - (CGFloat)cellHeight {
if (!_cellHeight) {
CGFloat contentW = [UIScreen mainScreen].bounds.size.width - * margin; // 屏幕宽度减去左右间距
CGFloat contentH = [self.content boundingRectWithSize:CGSizeMake(contentW, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:contentFont]}
context:nil].size.height;
_cellHeight = contentLabelY + contentH + margin;
}
return _cellHeight;
}
注意:
上面高度的计算还没有将内容图片的高度计算在内.
并且实现了利用模型的cellHeight属性缓存第一次计算高度.
  • 由于内容图片不是每个cell都有,所以使用代码动态添加.
 // 属性声明
@property (strong, nonatomic) UIImageView *contentImageView;
// getter实现
- (UIImageView *)contentImageView {
if (!_contentImageView) {
_contentImageView = [[UIImageView alloc] init];
[self.contentView addSubview:_contentImageView];
}
return _contentImageView;
}
  • cell该接收模型了
 @property (nonatomic, strong) Message *message;
- (void)setMessage:(Message *)message {
_message = message;
self.contentLabel.text = _message.content;
if (message.imageName.length) {
self.contentImageView.hidden = NO;
self.contentImageView.image = [UIImage imageNamed:message.imageName];
}
else {
self.contentImageView.hidden = YES;
}
}

当然,这时候contentImageView当然是显示不出来的,因为我们还没有赠送它一个frame.那么它的frame从何而来呢?

一开始我们说过,计算要基于模型,所以接下来的思路是由模型算出imageView的frame,拿去给cell用.

回到模型cellHeight的getter方法,添加对imageName属性的处理:

 // 图片将要展示的frame作为模型的其中一个属性
@property (nonatomic, assign) CGRect contentImageFrame;
- (CGFloat)cellHeight {
if (!_cellHeight) {
CGFloat contentW = [UIScreen mainScreen].bounds.size.width - * margin; // 屏幕宽度减去左右间距
CGFloat contentH = [self.content boundingRectWithSize:CGSizeMake(contentW, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:contentFont]}
context:nil].size.height;
_cellHeight = contentLabelY + contentH + margin; // 对imageName属性的处理
if (self.imageName.length) {
UIImage *image = [UIImage imageNamed:self.imageName];
CGFloat imageH = image.size.height;
CGFloat imageW = image.size.width;
// 直接得出contentImageView应该显示的frame
_contentImageFrame = CGRectMake(margin, _cellHeight, imageW, imageH);
_cellHeight += imageH + margin;
}
}
return _cellHeight;
}
当上面代码执行完毕,contentImageFrame就有值了.接着,回到cell的setMessage:方法给contentImageView赋值.
 - (void)setMessage:(Message *)message {
_message = message;
self.contentLabel.text = _message.content;
if (message.imageName.length) {
self.contentImageView.hidden = NO;
self.contentImageView.image = [UIImage imageNamed:message.imageName];
// 给图片的frame赋值,这个值就是上面得到那个
self.contentImageView.frame = _message.contentImageFrame;
}
else {
self.contentImageView.hidden = YES;
}
}
  • 这时候使用起来就非常轻松了
 // 控制器tableView协议方法实现
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
Message *message = self.dataList[indexPath.row];
return message.cellHeight;
}
完整代码下载:https://github.com/CoderAO/AutoCellHeightMix
 

UITableViewCell高度自适应探索--AutoLayout结合Frame的更多相关文章

  1. UITableViewCell高度自适应的关键点

    iOS开发中对于UITableViewCell高度自适应的文章已经很多很多,但如果cell内容比较复杂,刚使用autolayout配置自使用时还是总不能一次性成功. KEY POINT 这里只说设置的 ...

  2. uitableviewcell高度自适应笔记

    今天看了几篇uitableviewcell高度自适应的文章,大体分为两种方式. 第一种方式,cell里面有label,在cellforrow绘制的时候计算Label的可能高度,并且在此时重新计算cel ...

  3. UITableViewCell 高度自适应

    UITableViewCell 高度自适应一直是我们做动态Cell高度时遇到的最烦躁的问题,Cell动态高度计算可以去看看sunny的这篇文章介绍,今天主要和大家分享下我在使用systemLayout ...

  4. 原生的UITableViewCell高度自适应,textLabel自动换行显示

    /* * 设置子项cell **/ - (UITableViewCell *)getChildCell:(UITableView *)tableView and:(NSIndexPath *)inde ...

  5. 第二篇、为UITableViewCell 高度自适应加速 缓存cell的高度

    通过NSCache缓存已经算好的行高 @interface ZHCellHeightCalculator : NSObject //系统计算高度后缓存进cache -(void)setHeight:( ...

  6. autolayout 高度自适应

    https://lvwenhan.com/ios/449.html #import "ViewController.h" #import "MyTableViewCell ...

  7. UITableViewCell 高度计算从混沌初始到天地交泰

    [原创]UITableViewCell 高度计算从混沌初始到天地交泰 本文主要基予iOS UITableViewCell 高度自适应计算问题展开陈述,废话少说直入正题: UITableView控件可能 ...

  8. iframe框架自适应高度 uncanght SecurityError: Blocked a frame with origin "null" from accessing a frame ....

    来源于crm项目的contact/edit.html 一.背景是这样的 最近在做crm系统的前端页面,有一个页面呢,点击“查看全部信息”时会弹出,这个弹窗里面又有分页导航,分页不是使用ajax 异步刷 ...

  9. SnapKit swift实现高度自适应的新浪微博布局

    SnapKit swift版的自动布局框架,第一次使用感觉还不错. SnapKit是一个优秀的第三方自适应布局库,它可以让iOS.OS X应用更简单地实现自动布局(Auto Layout).GtiHu ...

随机推荐

  1. pci hole -- 被吞噬的内存

    参见wiki: http://en.wikipedia.org/wiki/PCI_hole PCI 空洞 pci 空洞是32位硬件和32位操作系统一个导致计算机显示的内存比实际安装的内存少的一个限制. ...

  2. DWZ使用笔记

    DWZ使用笔记 一.前言     在最近的一个项目中,引入了DWZ这个富客户端框架,算是一次尝试吧.期间也遇到不少问题,总算一一解决了.特以此文记之.     本人用的是dwz-ria-1.4.5+A ...

  3. [Hive - LanguageManual] GroupBy

    Group By Syntax Simple Examples Select statement and group by clause Advanced Features Multi-Group-B ...

  4. RStudio Keyboard Shortcuts

    Console Description Windows & Linux Mac Move cursor to Console Ctrl+2 Ctrl+2 Clear console Ctrl+ ...

  5. CodeForces 455A Boredom (DP)

    Boredom 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/G Description Alex doesn't like b ...

  6. UVaLive 7360 Run Step (排列组合,枚举)

    题意:给定一个数 n ,表示一共有 n 步,然后你可以迈一步也可以迈两步,但是左腿和右腿的一步和两步数要一样,并且两步数不小于一步数,问你有多少种方式. 析:虽然是排列组合,但还是不会做.....水啊 ...

  7. CodeForces 705A Hulk (水题)

    题意:输入一个 n,让你输出一行字符串. 析:很水题,只要判定奇偶性,输出就好. 代码如下: #pragma comment(linker, "/STACK:1024000000,10240 ...

  8. freemaker遍历嵌套list的map

    <#if disMap?exists> <#list disMap?keys as key> <#if ((disMap[key]))??&&((disM ...

  9. oracle中extents存在的理由

    extents的特性:1:一个extent由相连的多个blocks组成,多个extents组成一个segment,2:oracle在为segment分配空间时,是以extent为单位因此extents ...

  10. PostgreSQL的initdb 源代码分析之五

    接前面,继续分析: putenv("TZ=GMT") 设置了时区信息. find_other_exec(argv[0], "postgres", PG_BACK ...