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. 对Struts的理解

    1.struts是一个按MVC模式设计的Web层框架,其实他就是一个大大的servlet,这个Servlet名为ActionServlet,或是ActionServlet的子类.我们可以在web.xm ...

  2. web服务器分析与设计(三)

    面向对象分析与设计第二步:健壮性分析,完善对象 通过上一篇的分析,已经得到了构建系统中最重要的对象-----实体对象,它们封装着构成系统最重要的数据,实体数据是系统的生命. 但是光有实体还系统是运转不 ...

  3. 多级联动导航栏(top导航)

    http://www.dynamicdrive.com/style/csslibrary/item/jquery_multi_level_css_menu_2/ This is a multi-lev ...

  4. 《APUE》中的函数整理

    第1章 unix基础知识 1. char *strerror(int errnum) 该函数将errnum(就是errno值)映射为一个出错信息字符串,返回该字符串指针.声明在string.h文件中. ...

  5. HDFS体系结构

    HDFS的设计目标 检测以及快速恢复硬件问题. 流式的数据访问. 移动计算比移动数据的代价小. 简化一致性模型. 超大规模数据集 异构软硬件平台之间的可移植性. HDFS的结构模型HDFS是一个主从的 ...

  6. ocp 1Z0-042 1-60题解析

    1. Because of a power outage,instance failure has occurred. From what point in the redo log does rec ...

  7. Oracle的回收站和闪回查询机制(一)

    实际工作中,我们经常会遇到一些情况,误删除某些表或某些表的某些记录,这时候就需要我们将这些记录重新插入进去.如何才能解决这个问题呢? Oracle的Flashback query(闪回查询)为我们解决 ...

  8. jquery easyui防止超出浏览器边界

    var easyuiPanelOnMove=function(left,top){ if(left<0){ $(this).window('move',{ left:1 }); } if(top ...

  9. Codeforces Round #257 (Div. 1) C. Jzzhu and Apples (素数筛)

    题目链接:http://codeforces.com/problemset/problem/449/C 给你n个数,从1到n.然后从这些数中挑选出不互质的数对最多有多少对. 先是素数筛,显然2的倍数的 ...

  10. MFC通过对话框窗口句柄获得对话框对象指针

       C***Dialog* pWnd= (C***Dialog*)FromHandle(hWnd); //由句柄得到对话框的对象指针    pWnd->xxx( );              ...