通过storyboard方式来自定义不等高cell
- 添加子控件和contentView之间的间距约束
- 设置tableViewCell的真实行高和估算行高
// 告诉tableView所有cell的真实高度是自动计算(根据设置的约束来计算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
// 告诉tableView所有cell的估算高度
self.tableView.estimatedRowHeight = 44;
这种self-sizing技术,只支持从iOS8以后版本.
代码如下:
ZYStatus文件
#import
// 模型数据
@interface ZYStatus : NSObject
/** 图像 */
@property (nonatomic, copy) NSString *icon;
/** 昵称 */
@property (nonatomic, copy) NSString *name;
/** 正文(内容) */
@property (nonatomic, copy) NSString *text;
/** VIP */
@property (nonatomic, assign, getter=isVip) BOOL vip;
/** 配图 */
@property (nonatomic, copy) NSString *picture;
@end
@implementation ZYStatus
@end
ZYStatusCell文件
#import
@class ZYStatus;
@interface ZYStatusCell : UITableViewCell
/** 微博模型数据 */
@property(nonatomic,strong)ZYStatus *status;
@end
#import "ZYStatus.h"
@interface ZYStatusCell ()
/** 图像 */
@property (nonatomic, weak)IBOutlet UIImageView *iconImageView;
/** 昵称 */
@property (nonatomic, weak)IBOutlet UILabel *nameLabel;
/** vip */
@property (nonatomic, weak)IBOutlet UIImageView *vipImageView;
/** 正文 */
@property (nonatomic, weak)IBOutlet UILabel *text_Label;
/** 配图 */
@property (nonatomic, weak)IBOutlet UIImageView *pictureImageView;
/** 图片的高度约束 */
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureHeight;
/** 图片与cell底部的间距约束 */
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureBottomSpace;
@end
@implementation ZYStatusCell
3. 给子控件赋值
- (void)setStatus:(ZYStatus *)status
{
_status = status;
// 赋值
self.iconImageView.image = [UIImage imageNamed:status.icon];
self.nameLabel.text = status.name;
if (status.isVip) {
self.vipImageView.hidden = NO;
// 有if就有else,如果在这里写字体颜色,会出现数据紊乱,不是会员的用户的名称也是黄色
self.nameLabel.textColor = [UIColor orangeColor];
self.vipImageView.image = [UIImage imageNamed:@"vip"];
}else{
self.vipImageView.hidden = YES;
self.nameLabel.textColor = [UIColor blackColor];
}
self.text_Label.text = status.text;
if (status.picture) {
self.pictureImageView.hidden = NO;
self.pictureImageView.image = [UIImage imageNamed:status.picture];
// 因为有配图的cell,要设置配图的高度
self.pictureHeight.constant = 100;
self.pictureBottomSpace.constant = 10;
}else{
self.pictureImageView.hidden = YES;
// 如果没有配图的cell,要把配图高度约束设为0
self.pictureHeight.constant = 0;
self.pictureBottomSpace.constant = 0;
}
}
@end
Main.storyboard文件
ViewController文件
#import "ViewController.h"
#import "MJExtension.h"
#import "ZYStatusCell.h"
#import "ZYStatus.h"
@interface ViewController ()
/** 所有的微博 */
@property (nonatomic,strong) NSArray *statuses;
@end
@implementation ViewController
- (NSArray *)statuses
{
if (_statuses == nil) {
//加载plist中的数据到,模型ZYStatus中
_statuses = [ZYStatus mj_objectArrayWithFilename:@"statuses.plist"];
}
return _statuses;
}
- (void)viewDidLoad {
[super viewDidLoad];
// self-sizing技术,只适合ios8以上版本
// 告诉tableView所有cell的真实高度是自动计算的(根据设置的约束来计算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
// 告诉tableView所有cell的估算高度
self.tableView.estimatedRowHeight = 44;
}
#pragma -mark 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.statuses.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"status";
// 到缓存池中查看是否有可循环利用的cell
ZYStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 传递模型数据
cell.status = self.statuses[indexPath.row];
return cell;
}
@end
如果要支持iOS8之前
- 如果cell内部有自动换行的label,需要设置preferredMaxLayoutWidth属性
- (void)awakeFromNib
{
// 手动设置文字的最大宽度(目的是:让label知道自己文字的最大宽度,进而能够计算出自己的frame)
self.text_label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}
- 设置tableView的cell估算高度
// 告诉tableView所有cell的估算高度(设置了估算高度,就可以减少tableView:heightForRowAtIndexPath:方法的调用次数)
self.tableView.estimatedRowHeight = 200;
- 在代理方法中计算cell的高度
ZYStatusCell *cell;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 创建一个临时的cell(cell的作用:根据模型数据布局所有的子控件,进而计算出cell的高度)
if (!cell) {
cell = [tableView dequeueReusableCellWithIdentifier:ID];
}
// 设置模型数据
cell.status = self.statuses[indexPath.row];
return cell.height;
}
具体代码如下:
注意: 首先要取消storyboard中与contentView底部的间距
ZYStatus文件
// 模型数据
@interface ZYStatus : NSObject
/** 图像 */
@property (nonatomic, copy) NSString *icon;
/** 昵称 */
@property (nonatomic, copy) NSString *name;
/** 正文(内容) */
@property (nonatomic, copy) NSString *text;
/** VIP */
@property (nonatomic, assign, getter=isVip) BOOL vip;
/** 配图 */
@property (nonatomic, copy) NSString *picture;
@end
@implementation ZYStatus
@end
ZYStatusCell文件
#import
@class ZYStatus;
@interface ZYStatusCell : UITableViewCell
/** 微博模型数据 */
@property(nonatomic,strong)ZYStatus *status;
- (CGFloat)cellHeight;
@end
#import "ZYStatus.h"
@interface ZYStatusCell ()
/** 图像 */
@property (nonatomic, weak)IBOutlet UIImageView *iconImageView;
/** 昵称 */
@property (nonatomic, weak)IBOutlet UILabel *nameLabel;
/** vip */
@property (nonatomic, weak)IBOutlet UIImageView *vipImageView;
/** 正文 */
@property (nonatomic, weak)IBOutlet UILabel *text_Label;
/** 配图 */
@property (nonatomic, weak)IBOutlet UIImageView *pictureImageView;
@end
@implementation ZYStatusCell
3. 给子控件赋值
- (void)setStatus:(ZYStatus *)status
{
_status = status;
// 赋值
self.iconImageView.image = [UIImage imageNamed:status.icon];
self.nameLabel.text = status.name;
if (status.isVip) {
self.vipImageView.hidden = NO;
// 有if就有else,如果在这里写字体颜色,会出现数据紊乱,不是会员的用户的名称也是黄色
self.nameLabel.textColor = [UIColor orangeColor];
self.vipImageView.image = [UIImage imageNamed:@"vip"];
}else{
self.vipImageView.hidden = YES;
self.nameLabel.textColor = [UIColor blackColor];
}
self.text_Label.text = status.text;
if (status.picture) {
self.pictureImageView.hidden = NO;
self.pictureImageView.image = [UIImage imageNamed:status.picture];
}else{
self.pictureImageView.hidden = YES;
}
}
// 这个方法只会调用一次
- (void)awakeFromNib
{
// 手动设置文字的最大宽度(让label能够计算出自己最真实的尺寸)
self.text_Label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}
- (CGFloat)cellHeight
{
// self.text_Label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
[self layoutIfNeeded];
CGFloat cellHeight = 0;
if (self.status.picture) { //有配图
cellHeight = CGRectGetMaxY(self.pictureImageView.frame) + 10;
}else{ // 无配图
cellHeight = CGRectGetMaxY(self.text_Label.frame) + 10;
}
return cellHeight;
}
@end
ViewController文件
#import "ViewController.h"
#import "MJExtension.h"
#import "ZYStatusCell.h"
#import "ZYStatus.h"
@interface ViewController ()
/** 所有的微博 */
@property (nonatomic,strong) NSArray *statuses;
@end
@implementation ViewController
- (NSArray *)statuses
{
if (_statuses == nil) {
//加载plist中的数据到,模型ZYStatus中
_statuses = [ZYStatus mj_objectArrayWithFilename:@"statuses.plist"];
}
return _statuses;
}
- (void)viewDidLoad {
[super viewDidLoad];
// cell的估算高度(作用: 性能优化,减少heightForRowAtIndexPath方法的调用次数)
// 假如一个cell的高度为100.iphone6的高度为650,所以会打印7次heightForRowAtIndexPath方法,来快速\
估算有多少cell要显示
self.tableView.estimatedRowHeight = 100;
}
#pragma -mark 数据源方法
NSString *ID = @"status";
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.statuses.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 到缓存池中查看是否有可循环利用的cell
ZYStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 传递模型数据
cell.status = self.statuses[indexPath.row];
return cell;
}
ZYStatusCell *cell;
#pragma -mark 代理方法
// 系统之所以调用多次这个方法,为了计算contentSize的滚动范围,为了用户体验,计算滚动条的长度.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (cell == nil) {
cell = [tableView dequeueReusableCellWithIdentifier:ID];
}
cell.status = self.statuses[indexPath.row];
return cell.cellHeight;
}
@end