一、静态cell和动态cell
一般比较固定的样式可通过storyboard中的静态cell或者动态cell进行操作,方便快捷高效。
静态cell创建方式
动态cell创建方式
二、纯代码是实现自定义不等高cell
下面通过案例来实现用纯代码的方式来完成自定义不等高cell的实现。
项目需求:
以微博为例,当别人发状态时,有的人发文字,有的人发文字和图片,那么如何实现这种方式呢?
项目思路:
在UITableViewCell中的系统样式中不能满足项目所需,那么我们首先得想,通过自定义cell的方式来完成,至于高度不等,那么我们可以在每一个cell中通过判断哪个控件是最后一个,然后就取它的高度然后和cell底部间留有间距就完成了。
项目实现过程:
1.创建项目,导入图片及plist文件
2.创建数据模型,用来进行plist字典数据转模型
3.创建一个继承自UITableViewCell的文件用来设置自定义cell以及数据的重写
4.在控制器中遵守UITableViewDataSourse协议,创建代理对象,实现代理方法等。
项目代码编码过程:
1.创建项目,导入图片及plist文件
2.创建ZJStatus数据模型
在ZJStatus.h中
/* 内容数据***********/
/* 头像 /
@property (nonatomic ,copy)NSString *icon;
/* 昵称 /
@property (nonatomic ,copy)NSString *name;
/* vip /
@property (nonatomic ,assign)BOOL vip;
/* 文字 /
@property (nonatomic ,copy)NSString *text;
/* 图片 /
@property (nonatomic ,copy)NSString *picture;
在ZJStatus.m中不做任何操作
(3)创建ZJStatusCell文件用来设置自定cell以及重写数据
在ZJStatusCell.h中
先导入@class ZJStatus;
将ZJStatus 所有属性进行声明
/* status的数据 /
@property (nonatomic,strong) ZJStatus *status;
在ZJStatusCell.m中
#import "ZJStatus.h"
#define KNameFont [UIFont systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]
@interface ZJStatusCell ()
// 声明一些属性
#import "ZJStatus.h"
#define KNameFont [UIFont
// 定义宏
systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]
@interface ZJStatusCell ()
/** 头像 */
@property (nonatomic ,weak)UIImageView *iconImageView;
/** 昵称 */
@property (nonatomic ,weak)UILabel *nameLabel;
/** vip */
@property (nonatomic ,weak)UIImageView * vipImageView;
/** 文字 */
@property (nonatomic ,weak)UILabel *TEXTLabel;
/** 图片 */
@property (nonatomic ,weak)UIImageView *pictureImageView;
@end
@implementation ZJStatusCell
/**
* 添加子控件(把有可能显示的子控件都加进去)
*/
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// 1.昵称
UIImageView *iconImageView = [[UIImageView alloc]init];
[self.contentView addSubview:iconImageView];
// 连线 建立关系
self.iconImageView = iconImageView;
// 2.标题
UILabel *nameLabel = [[UILabel alloc]init];
[self.contentView addSubview:nameLabel];
self.nameLabel = nameLabel;
// 设置文字大小
self.nameLabel.font = KNameFont;
// 连线 建立关系
self.nameLabel = nameLabel;
// 3.vip
UIImageView *vipImageView = [[UIImageView alloc]init];
vipImageView.image = [UIImage imageNamed:@"vip"];
// 图片显示格式
vipImageView.contentMode = UIViewContentModeCenter;
[self.contentView addSubview:vipImageView];
// 连线 建立关系
self.vipImageView = vipImageView;
// 4.文字
UILabel *TEXTlabel = [[UILabel alloc]init];
[self.contentView addSubview:TEXTlabel];
self.TEXTLabel = TEXTlabel;
// 设置文字大小
self.TEXTLabel.font = KTextFont;
// 连线 建立关系
self.TEXTLabel = TEXTlabel;
// 换行
self.TEXTLabel.numberOfLines = 0;
// 设置一个背景颜色
self.TEXTLabel.backgroundColor = [UIColor redColor];
// 5.配图
UIImageView *pictureImageView = [[UIImageView alloc]init];
[self.contentView addSubview:pictureImageView];
self.pictureImageView = pictureImageView;
// 连线 建立关系
self.pictureImageView = pictureImageView;
}
return self;
}
// 布局子控件
- (void)layoutSubviews{
#warning 一定要调用 [super layoutSubviews];
[super layoutSubviews];
CGFloat margin = 10;
// 1.设置头像的位置
CGFloat iconX = margin;
CGFloat iconY = margin;
CGFloat iconW = 40;
CGFloat iconH = iconW;
self.iconImageView.frame = CGRectMake(iconX, iconY, iconW, iconH);
// 2.设置标题位置
CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
CGFloat nameY = iconY;
// 计算文字所占据的尺寸
NSDictionary *nameAttri = @{NSFontAttributeName :KNameFont
};
CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
// 包装成结构体
self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};
// 3.设置vip图标
if (self.status.vip) {
CGFloat vipX = CGRectGetMaxX(self.nameLabel.frame) + margin;
CGFloat vipY = nameY;
CGFloat vipW = 14;
CGFloat vipH = nameSize.height;
self.vipImageView.frame = CGRectMake(vipX, vipY, vipW, vipH);
}
// 4.文字
CGFloat textX = iconX;
CGFloat textY = CGRectGetMaxY(self.iconImageView.frame) + margin;
CGFloat textW = self.contentView.frame.size.width - iconX * 2;
CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
NSDictionary *textSize = @{NSFontAttributeName:KTextFont
};
CGFloat textH = [self.status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;
self.TEXTLabel.frame = CGRectMake(textX, textY, textW, textH);
// 配图
if (self.status.picture) {
CGFloat pictureX = textX;
CGFloat pictureY = CGRectGetMaxY(self.TEXTLabel.frame) +margin;
CGFloat pictureW = 100;
CGFloat pictureH = pictureW;
self.pictureImageView.frame = CGRectMake(pictureX, pictureY, pictureW, pictureH);
}
}
- (void)setStatus:(ZJStatus *)status{
_status = status;
self.iconImageView.image = [UIImage imageNamed:status.icon];
self.nameLabel.text = status.name;
self.TEXTLabel.text = status.text;
// 图片
if (status.picture) {
self.pictureImageView.hidden = NO;
self.pictureImageView.image = [UIImage imageNamed:status.picture];
}
else {
self.pictureImageView.hidden = YES;
}
// vip 图标
if (status.vip) {
self.vipImageView.hidden = NO;
self.nameLabel.textColor = [UIColor orangeColor];
}else{
self.vipImageView.hidden = YES;
self.nameLabel.textColor = [UIColor blackColor];
}
}
在控制器中:
#import "ZJStatus.h"
#import "ZJStatusCell.h"
// 导入第三方数据转模型框架MJExtension
#import "MJExtension.h"
@interface ViewController ()
/** status的数组 */
@property (nonatomic,strong) NSArray *statuses;
@end
@implementation ViewController
- (NSArray *)statuses{
if (!_statuses) {
_statuses = [ZJStatus objectArrayWithFilename:@"statuses.plist"];
}
return _statuses;
}
NSString *ID = @"status";
- (void)viewDidLoad {
[super viewDidLoad];
// 注册
[self.tableView registerClass:[ZJStatusCell class] forCellReuseIdentifier:ID];
}
#pragma mark - 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.statuses.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
ZJStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
cell.status = self.statuses[indexPath.row];
return cell
;
}
#pragma mark - 通过代理方法来算高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
// 从模型中取出数据
ZJStatus *status = self.statuses[indexPath.row];
CGFloat margin = 10;
CGFloat cellHeight = 0;
// 1.设置头像的位置
CGFloat iconX = margin;
CGFloat iconY = margin;
CGFloat iconW = 40;
CGFloat iconH = iconW;
CGRect iconImageView = CGRectMake(iconX, iconY, iconW, iconH);
// 2.文字
CGFloat textX = iconX;
CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;
CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
};
CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;
CGRect TEXTLabel = CGRectMake(textX, textY, textW, textH);
// 配图
if (status.picture) {
CGFloat pictureX = textX;
CGFloat pictureY = CGRectGetMaxY(TEXTLabel) +margin;
CGFloat pictureW = 100;
CGFloat pictureH = pictureW;
CGRect pictureImageView = CGRectMake(pictureX, pictureY, pictureW, pictureH);
// 如果有图片 cellHeight的Y就等于图片的最大值
cellHeight = CGRectGetMaxY(pictureImageView);
}
else {
// 如果没有图片 cellHeight的Y就等于文字边距的最大值
cellHeight = CGRectGetMaxY(TEXTLabel);
}
cellHeight += margin;
return cellHeight;
}
这种完成自定义不等高cell方式很low在实现代理方法来算高度的时候又把ZJStatusView中的设置位置方式写了一遍,这样写性能会有所下降,为了提高性能,可采用MVVM设计模式进行实现,后面会单另做MVVC设计模式的分享 。
三、根据文字来创建自适应大小方式。
// 自适应文字及高度显示
CGFloat textX = iconX;
CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
// 设置文字的自适应宽度 ,屏幕的宽度减去两边的间距
CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;
// 设置文字显示的最大高度
CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
// 字典包装文字本身大小
NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
};
// 算出文字的自适应高度
CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;
CGRect TEXTLabel = CGRectMake(textX, textY, textW, textH);
// 自适应文字宽度显示
CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
CGFloat nameY = iconY;
// 计算文字本身所占据的尺寸
NSDictionary *nameAttri = @{NSFontAttributeName :[UIFont systemFontOfSize:14.0]
};
CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
// 包装成结构体
self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};