[How to] 动态布局可变高度的cell的应用
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的应用的更多相关文章
- 使用Autolayout实现UITableView的Cell动态布局和高度动态改变
本文翻译自:stackoverflow 有人在stackoverflow上问了一个问题: 1 如何在UITableViewCell中使用Autolayout来实现Cell的内容和子视图自动计算行高,并 ...
- 设置UILabel可变高度(根据文本内容自动适应高度)
@property(nonatomic)UILabel *showLabel; // 计算文本所占高度,计算出来之后设置label的高度 // 第一个参数:字体大小,字体大小/样式影响计算字体的高 ...
- 转:动态计算UITableViewCell高度详解
转自:http://www.cocoachina.com/industry/20140604/8668.html 不知道大家有没有发现,在iOS APP开发过程中,UITableView是我们显示 ...
- 动态计算UITableViewCell高度详解
本文将介绍四种情况下UITableViewCell的计算方式,分别是: Auto Layout with UILabel in UITableViewCell Auto Layout with UIT ...
- 动态计算UITableViewCell高度详解 (转)
感觉挺有用的一篇文章,分析了4种解决方案.回头测试之.如果有别的方案,我会在后面补上. 原文地址:http://www.ifun.cc/blog/2014/02/21/dong-tai-ji-suan ...
- 动态计算UITableViewCell高度
动态计算UITableViewCell高度 UILabel in UITableViewCell Auto Layout - UILabel的属性Lines设为了0表示显示多行.Auto Layout ...
- android开发学习笔记系列(4)--android动态布局
前言 在做一个有关苏果APP的项目中,但是fuck的是,我完全使用相对布局之后及线性布局之后发现坑爹的事情了,屏幕不能适配,这是多大的痛,意味着,必须使用相应的代码实现动态布局!呵呵,不做项目不知道, ...
- 动态调整UITableViewCell高度的实现方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPa ...
- 【腾讯Bugly干货分享】Android动态布局入门及NinePatchChunk解密
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ff5d53bbcffd68c64411 作者:黄进——QQ音乐团队 摆脱 ...
随机推荐
- 用select (多路复用)模拟一个 socket server
需求:用select (多路复用)模拟一个 socket server.可以接收多并发. 1. 一开始是检测自己,如果我有活动了,就说明有客户端要连我了. #用select去模拟socket,实现单线 ...
- [BZOJ5303] [HAOI2018] 反色游戏
题目链接 LOJ:https://loj.ac/problem/2524 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5303 洛谷:https ...
- [洛谷P2408]不同子串个数
题目大意:给你一个字符串,求其中本质不同的字串的个数 题解:同[洛谷P4070][SDOI2016]生成魔咒,只要最后再输出就行了 卡点:无 C++ Code: #include <cstdio ...
- BZOJ4589:Hard Nim——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4589 Claris和NanoApe在玩石子游戏,他们有n堆石子,规则如下: 1. Claris和N ...
- BZOJ2730:[HNOI2012]矿场搭建——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2730 https://www.luogu.org/problemnew/show/P3225 听说 ...
- BZOJ1911:[Apio2010]特别行动队——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1911 又是一个显然的dp……好吧我懒得讲了. s[i]是战斗力前缀和. 我们仍然设k<j< ...
- UVA.12096 The SetStack Computer ( 好题 栈 STL混合应用)
UVA.12096 The SetStack Computer ( 好题 栈 STL混合应用) 题意分析 绝对的好题. 先说做完此题的收获: 1.对数据结构又有了宏观的上的认识; 2.熟悉了常用STL ...
- Bazinga 字符串HASH 这题不能裸HASH 要优化 毒瘤题
Ladies and gentlemen, please sit up straight. Don't tilt your head. I'm serious. For nn given string ...
- 使用html5的Geolocation API实现定位
公司有个需求,需要获取用户的位置,所以看了下html5的Geolocation 这个新东西,发现挺好用的. <!DOCTYPE html> <html> <body> ...
- ZooKeeper文档(二)
ZooKeeper:因为协调的分布式系统是一个动物园 ZooKeeper对分布式应用来说是一个高性能的协调服务.它暴露通常的服务-比如命名,配置管理,同步,和组服务-用一种简单的接口,所以你不用从头开 ...