1.简介

代码:https://github.com/xufeng79x/DynamicChangeableCell

微博界面,微信和QQ聊天界面,这些界面的布局大都不确定,且每一条消息的高度也不一样。在TableView的代理UITableViewDelegate的heightForRowAtIndexPath中可以动态的定义每一行的高度,但是我们需要得到cell的内容后才能最终确认当前的cell到底需要多少高度,而得到cell的方法是代理UITableViewDataSource的cellForRowAtIndexPath方法,从断点debug手段来看,系统都是先调用heightForRowAtIndexPath方法然后在调用cellForRowAtIndexPath方法,所以从调用顺序来看,在heightForRowAtIndexPath之前就需要将高度信息计算出来。

2.目标

代码:https://github.com/xufeng79x/DynamicChangeableCell

如下图模拟了一个简单的微博界面,此界面极大简化了复杂度,只包含一个头像和文本内容。但是对一个demo用于解释此场景已经足够了。

3.实现

对于很多变化多样的cell来说,固定布局的xib活着直接storyborad已经无法满足要求,cell中高度,cell中各个控件的布局或者是否显示等是可变的。因此我们我们唯有使用代码去

创建控件并根据具体条件去设置他们。

关键步骤讲解:

1.创建自定义cell:

重用cell,并且重写构造方法,在构造方法中去创建各个控件,但是其并不包含frame信息。在微博或者qq等场景中控件的frame都不是固定的。

所以我们不能通过xib那样的方式去实现而只能使用代码的动态创建来完成。

/**
 *  创建cell
 *
 *  @param tableView 宿主table
 *
 *  @return cell
 */
+(instancetype) webCellWithTableView:(UITableView *)tableView
{
    // 根据可ID进行cell的可重用查找
    static NSString *reuseId = @"webcell";
    XFWebTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];

    if (!cell) {
        cell = [[self alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseId];
    }

    return cell;

}

/**
 *  重写父类的方法
 *
 *  @param style           重写父类初始化方法并创建子类的控件
 *  @param reuseIdentifier 重用ID
 *
 *  @return cell
 */
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        // 开始创建子控件
        // 头像
        UIImageView *picView = [[UIImageView alloc] init];
        [self.contentView addSubview:picView];
        self.picView = picView;

        // 内容
        UILabel *textView = [[UILabel alloc] init];
        textView.font = [UIFont systemFontOfSize:XF_TEXT_FONT];
        textView.numberOfLines = ;
        [self.contentView addSubview:textView];
        self.textView = textView;
    }

    return self;
}

2.创建含有frame信息的模型类,其中根据数据模型对象来创建各个控件的frame信息

#import <UIKit/UIKit.h>

// 字体大小设定
#define XF_TEXT_FONT 15

@class XFWebModel;

/**
 *  微博cell的布局信息和数据信息集合
 */
@interface XFWebFrame : NSObject

// 当前cell的数据
@property(nonatomic, strong) XFWebModel *webInfo;

 // 当前cell所需要的高度
@property(nonatomic,assign,readonly) NSInteger cellHight;

// 头像空间的frame
@property(nonatomic,assign,readonly) CGRect picFrame;

// 正文控件frame
@property(nonatomic, assign,readonly) CGRect textFrame;

/**
 *  类构造方法,用于返回每一行微博数据和布局列表
 *
 *  @return 布局信息和微博信息
 */
+(NSMutableArray *)webFrames;

@end

3.在Controller中起plist中加载数据的时候就直接创建了含有frame信息的对象列表:

/**
 *  懒加载web数据
 *
 *  @return 微博数据
 */
- (NSMutableArray *)webFrames
{
    if (!_webFrames) {
        _webFrames = [XFWebFrame webFrames];
    }

    return _webFrames;
}

4.在上述加载过程中,我们需要计算每一条微博的cell的布局信息:

/**
 *  记载数据并计算布局
 *
 *  @param webInfo 记载数据并计算布局
 */
-(void) setWebInfo:(XFWebModel *)webInfo{
    // 数据设定
    _webInfo = webInfo;

    // 开始计算布局
    [self calculateFrameWithInfo:webInfo];
}

/**
 *  计算布局
 *
 *  @param webInfo 计算每一行微博的布局
 */
- (void)calculateFrameWithInfo:(XFWebModel *)webInfo
{
    CGFloat margin = ;

    // 头像
    CGFloat picW = ;
    CGFloat picH = ;
    CGFloat picX = margin;
    CGFloat picY = margin;
    _picFrame = CGRectMake(picX, picY, picW, picH);

    // 正文
    CGSize textSize = [self sizeWithText:self.webInfo.content maxSize:CGSizeMake(, MAXFLOAT) fontSize:XF_TEXT_FONT];
    CGFloat textX = picX;
    CGFloat textY = CGRectGetMaxY(self.picFrame) + margin;
    _textFrame = CGRectMake(textX, textY, textSize.width, textSize.height);

    // 计算行高
    _cellHight = CGRectGetMaxY(self.textFrame) + margin;

}

5.在Controller中每一条微博的cell布局和内容信息都直接传递给自定义cell对象,而高度已经在上述懒加载过程都已经计算出来直接使用即可。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // 将微博信息与其布局信息传递至自定义cell
    XFWebTableViewCell *cell = [XFWebTableViewCell webCellWithTableView:tableView];
    cell.webFrame = self.webFrames[indexPath.row];
    return cell;
}

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //高度已经计算完成,直接使用
    XFWebFrame *frame = self.webFrames[indexPath.row];
    return frame.cellHight;
}

6.在自定义cell中根据Controller传入的frame对象信息在将各个控件的frame进行调整并将微博内容

// 接受微博信息和布局信息
- (void)setWebFrame:(XFWebFrame *)webFrame
{
    _webFrame = webFrame;

    // 设置内容
    self.picView.image = [UIImage imageNamed:webFrame.webInfo.photo];
    self.textView.text = webFrame.webInfo.content;

    // 设置布局
    self.picView.frame = webFrame.picFrame;
    self.textView.frame = webFrame.textFrame;
}

  

4.总结:

本文主要说明对于动态cell(高度,控件内容,frame每一个cell都不一致)需要我们在得到数据后在直接将布局高度等信息计算出来,在加载cell中将这些信息传入自定义cell中设定相应的frame。

[How to] 动态布局可变高度的cell的应用的更多相关文章

  1. 使用Autolayout实现UITableView的Cell动态布局和高度动态改变

    本文翻译自:stackoverflow 有人在stackoverflow上问了一个问题: 1 如何在UITableViewCell中使用Autolayout来实现Cell的内容和子视图自动计算行高,并 ...

  2. 设置UILabel可变高度(根据文本内容自动适应高度)

    @property(nonatomic)UILabel *showLabel;   // 计算文本所占高度,计算出来之后设置label的高度 // 第一个参数:字体大小,字体大小/样式影响计算字体的高 ...

  3. 转:动态计算UITableViewCell高度详解

    转自:http://www.cocoachina.com/industry/20140604/8668.html   不知道大家有没有发现,在iOS APP开发过程中,UITableView是我们显示 ...

  4. 动态计算UITableViewCell高度详解

    本文将介绍四种情况下UITableViewCell的计算方式,分别是: Auto Layout with UILabel in UITableViewCell Auto Layout with UIT ...

  5. 动态计算UITableViewCell高度详解 (转)

    感觉挺有用的一篇文章,分析了4种解决方案.回头测试之.如果有别的方案,我会在后面补上. 原文地址:http://www.ifun.cc/blog/2014/02/21/dong-tai-ji-suan ...

  6. 动态计算UITableViewCell高度

    动态计算UITableViewCell高度 UILabel in UITableViewCell Auto Layout - UILabel的属性Lines设为了0表示显示多行.Auto Layout ...

  7. android开发学习笔记系列(4)--android动态布局

    前言 在做一个有关苏果APP的项目中,但是fuck的是,我完全使用相对布局之后及线性布局之后发现坑爹的事情了,屏幕不能适配,这是多大的痛,意味着,必须使用相应的代码实现动态布局!呵呵,不做项目不知道, ...

  8. 动态调整UITableViewCell高度的实现方法

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPa ...

  9. 【腾讯Bugly干货分享】Android动态布局入门及NinePatchChunk解密

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ff5d53bbcffd68c64411 作者:黄进——QQ音乐团队 摆脱 ...

随机推荐

  1. POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释

    http://poj.org/problem?id=1389 题面描述在二维xy平面中有N,1 <= N <= 1,000个矩形.矩形的四边是水平或垂直线段.矩形由左下角和右上角的点定义. ...

  2. BZOJ3224:普通平衡树——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3224 题面源于洛谷 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下 ...

  3. JS获取移动端系统信息(操作系统、操作系统版本、横竖屏状态、设备类型、网络状态、生成浏览器指纹)

    function getOS() { // 获取当前操作系统 var os; if (navigator.userAgent.indexOf('Android') > -1 || navigat ...

  4. mysql中设置小数

    decimal Decimal(n,m)表示数值中共有n位数,其中整数n-m位,小数m位.例:decimal(10,6),数值中共有10位数,其中整数占4位,小数占6位. 例:decimal(2,1) ...

  5. nodejs formidable混合表单提交

    废话不多说,直接上代码: 前端页面: <!DOCTYPE html><html><head><link rel=’stylesheet’ href=’/sty ...

  6. 更改本地hosts文件

    在 C:\Windows\System32\drivers\etc 下更改 hosts 文件 127.0.0.1 www.baidu.com 这样访问 www.baidu.com 这个地址,其实是访问 ...

  7. 转:Java中的equals和hashCode方法详解

    转自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这 ...

  8. 图论:最短路-Bellman-Ford

    我们之前介绍了一种,(最常用的)SPFA算法,SPFA算法是对Bellman-Ford算法的队列优化,用队列替代了Bellman-Ford中的循环检查部分 然后这里我们介绍Bellman-Ford算法 ...

  9. LightOJ 1326 – Race 第二类Stirling数/

    简单的模板题. 题意:问n匹马出现的不同排名数. 题解:可以使用DP,本质上还是第二类Stirling数(隔板法) #include <stdio.h> #include <iost ...

  10. 2018 Multi-University Training Contest 1-1002 -Balanced Sequence(括号匹配+贪心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6299 题目: 题意:t组数据,每组数据给你一个n表示给你n个括号串,这n个括号串之间进行组合,求能够匹 ...