等高的Cell
一、storyboard方式
创建一个继承自UITableViewCell的子类
在storyboard中
- 往cell里面增加需要用到的子控件
- 设置cell的重用标识
- 设置cell的class为我刚才创建的那个Cell类型XXDealCell
3. 在控制器中
- 利用重用标识找到cell
- 给cell传递模型数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.deals.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"deal"; XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //取出模型数据 cell.deal = self.deals[indexPath.row]; return cell;}
4.在XXDealCell中,将storyboard中的子控件连线到类扩展中,并且提供一个模型属性,重写模型的set方法,在这个方法中设置模型数据到子控件上。
//// XXDealCell.m// 自定义等高的cell//// Created by Daniel on 16/3/17.// Copyright © 2016年 Daniel. All rights reserved.//#import "XXDealCell.h"#import "XXDeal.h"@interface XXDealCell()@property (weak, nonatomic) IBOutlet UIImageView *iconView;@property (weak, nonatomic) IBOutlet UILabel *titleLable;@property (weak, nonatomic) IBOutlet UILabel *priceLable;@property (weak, nonatomic) IBOutlet UILabel *buyCountLable;@end@implementation XXDealCell- (void)setDeal:(XXDeal *)deal { _deal = deal; //设置数据 self.iconView.image = [UIImage imageNamed:deal.icon]; self.titleLable.text = deal.title; self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price]; self.buyCountLable.text = [NSString stringWithFormat:@"%@人已购买", deal.buyCount]; }@end
二、xib方式
1.创建一个继承自UITableViewCell的子类,比如XXDealCell
2.创建一个xib文件(文件名建议跟cell的类名一样),比如XXDealCell.xib,拖拽一个UITableViewCell出来,修改cell的class为XXDealCell,设置cell的重用标识,往cell中添加需要用到的子控件
这两步和storyboard方式都是大同小异。
3.在控制器中,利用registerNib...方法注册xib文件,利用重用标识找到cell(如果没有注册xib文件,就需要手动去加载xib文件),给cell传递模型数据。
- (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XXDealCell class]) bundle:nil] forCellReuseIdentifier:@"deal"]; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"deal"; XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //如果不注册,就要这样手动加载xib// if(cell == nil) {// cell = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([XXDealCell class]) owner:nil options:nil]lastObject];// } //取出模型数据 cell.deal = self.deals[indexPath.row]; return cell;}
4.在XXDealCell中,将xib中的子控件连线到类扩展中,需要提供一个模型属性,重写模型的set方法,在这个方法中设置模型数据到子控件上,也可以将创建获得cell的代码封装起来(比如cellWithTableView:方法)
//// XXDealCell.m// 自定义等高的cell//// Created by Daniel on 16/3/17.// Copyright © 2016年 Daniel. All rights reserved.//#import "XXDealCell.h"#import "XXDeal.h"@interface XXDealCell()@property (weak, nonatomic) IBOutlet UIImageView *iconView;@property (weak, nonatomic) IBOutlet UILabel *titleLable;@property (weak, nonatomic) IBOutlet UILabel *priceLable;@property (weak, nonatomic) IBOutlet UILabel *buyCountLable;@end@implementation XXDealCell- (void)setDeal:(XXDeal *)deal { _deal = deal; //设置数据 self.iconView.image = [UIImage imageNamed:deal.icon]; self.titleLable.text = deal.title; self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price]; self.buyCountLable.text = [NSString stringWithFormat:@"%@人已购买", deal.buyCount]; }+ (instancetype)cellWithTableView:(UITableView *) tableView { static NSString *ID = @"deal"; XXDealCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if(cell == nil) { cell = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([XXDealCell class]) owner:nil options:nil]lastObject]; } return cell; }@end
- (void)viewDidLoad { [super viewDidLoad]; // [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XXDealCell class]) bundle:nil] forCellReuseIdentifier:@"deal"]; }#pragma mark - Table view data source- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.deals.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XXDealCell *cell = [XXDealCell cellWithTableView:tableView]; //取出模型数据 cell.deal = self.deals[indexPath.row]; return cell;}
三、代码方式
-------------使用frame
1.创建一个继承自UITableViewCell的子类,比如XXDealCell
- 在initWithStyle:reuseIdentifier:方法中添加子控件,设置子控件的初始化属性(比如文字颜色、字体)等
- 在layoutSubviews方法中设置子控件的frame
- 需要提供一个模型属性,重写模型的setter方法,在这个方法中设置模型数据到子控件
//1、在initWithStyle:reuseIdentifier:方法中添加子控件- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if(self == [super initWithStyle:style reuseIdentifier:reuseIdentifier ]) { UIImageView *iconView = [[UIImageView alloc]init]; [self.contentView addSubview:iconView]; self.iconView = iconView; UILabel *titleLable = [[UILabel alloc]init]; [self.contentView addSubview:titleLable]; self.titleLable = titleLable; UILabel *priceLable = [[UILabel alloc]init]; [self.contentView addSubview:priceLable]; priceLable.textColor = [UIColor orangeColor]; self.priceLable = priceLable; UILabel *buyCountLable = [[UILabel alloc]init]; [self.contentView addSubview:buyCountLable]; buyCountLable.textAlignment = NSTextAlignmentRight; buyCountLable.font = [UIFont systemFontOfSize:11]; buyCountLable.textColor = [UIColor lightGrayColor]; self.buyCountLable = buyCountLable; } return self;}//2、在layoutSubviews方法中设置子控件的frame- (void)layoutSubviews { [super layoutSubviews]; //iconView CGFloat iconX = 10; CGFloat iconY = 10; CGFloat iconW = 100; CGFloat iconH = self.contentView.frame.size.height - 2 * iconY; self.iconView.frame = CGRectMake(iconX, iconY, iconW, iconH); //titleLable CGFloat titleX = CGRectGetMaxX(self.iconView.frame) + 10; CGFloat titleY = iconY; CGFloat titleW = self.contentView.frame.size.width - titleX - 10; CGFloat titleH = 20; self.titleLable.frame = CGRectMake(titleX, titleY, titleW, titleH); //priceView CGFloat priceX = titleX; CGFloat priceH = 20; CGFloat priceY = self.contentView.frame.size.height - priceH - 10; CGFloat priceW = 70; self.priceLable.frame = CGRectMake(priceX, priceY, priceW, priceH); //buyCountView CGFloat buyH = priceH; CGFloat buyY = self.contentView.frame.size.height - 10 - buyH; CGFloat buyX = priceX + priceW + 10; CGFloat buyW = self.contentView.frame.size.width - buyX - 10; self.buyCountLable.frame = CGRectMake(buyX, buyY, buyW, buyH); }//3、重写模型的setter方法- (void)setDeal:(XXDeal *)deal { _deal = deal; //设置数据 self.iconView.image = [UIImage imageNamed:deal.icon]; self.titleLable.text = deal.title; self.priceLable.text = [NSString stringWithFormat:@"¥%@", deal.price]; self.buyCountLable.text = [NSString stringWithFormat:@"%@人已购买", deal.buyCount]; }
2.在控制器中,利用registerClass...方法注册XMGDealCell类,利用重用标识找到cell(如果没有注册类,就需要手动创建cell,给cell传递模型数据,也可以将创建获得cell的代码封装起来(比如cellWithTableView:方法)。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XXDealCell *cell = [XXDealCell cellWithTableView:tableView]; //取出模型数据 cell.deal = self.deals[indexPath.row]; return cell;}
---------------------使用autoLayout
与使用frame不同的是:在initWithStyle:reuseIdentifier:方法中添加子控件后直接添加约束,然后不需要layoutSubviews方法了。其他都是一样的,添加约束使用Masonry。
//1、在initWithStyle:reuseIdentifier:方法中添加子控件- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if(self == [super initWithStyle:style reuseIdentifier:reuseIdentifier ]) { CGFloat margin = 10; UIImageView *iconView = [[UIImageView alloc]init]; [self.contentView addSubview:iconView]; self.iconView = iconView; [iconView makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(100); make.left.top.equalTo(self.contentView).offset(margin); make.bottom.equalTo(self.contentView).offset(-margin); }]; UILabel *titleLable = [[UILabel alloc]init]; [self.contentView addSubview:titleLable]; self.titleLable = titleLable; [titleLable makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(iconView.right).offset(margin); make.top.equalTo(iconView); make.right.equalTo(self.contentView).offset(-margin); }]; UILabel *priceLable = [[UILabel alloc]init]; [self.contentView addSubview:priceLable]; priceLable.textColor = [UIColor orangeColor]; self.priceLable = priceLable; [priceLable makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(titleLable); make.bottom.equalTo(iconView); }]; UILabel *buyCountLable = [[UILabel alloc]init]; [self.contentView addSubview:buyCountLable]; buyCountLable.textAlignment = NSTextAlignmentRight; buyCountLable.font = [UIFont systemFontOfSize:11]; buyCountLable.textColor = [UIColor lightGrayColor]; self.buyCountLable = buyCountLable; [buyCountLable makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(priceLable); make.right.equalTo(self.contentView).offset(-margin); make.left.equalTo(priceLable).offset(margin); }]; } return self;}
非等高cell
xib自定义非等高cell
- 在模型中增加一个cellHeight属性,用来存放对应cell的高度
/** * cell的高度 */@property(assign, nonatomic)CGFloat cellHeight;
- 在cell的模型属性setter方法中调用[self layoutIfNeed]方法强制布局,然后计算出模型的cellheight属性值
//强制布局[self layoutIfNeeded];
- 在控制器中实现tableView:estimatedHeightForRowAtIndexPath:方法,返回一个估计高度
/** * 返回每一个cell的估计高度 * * @param tableView * @param indexPath * * @return 只要返回了估计高度,tableView就会先调用tableView:cellForRowAtIndexPath:方法创建cell * 再调用tableView:heightForRowAtIndexPath:方法获取cell的真实高度 */- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { return 100;}
- 在控制器中实现tableView:heightForRowAtIndexPath:方法,返回cell的真实高度(模型中的cellHeight属性)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XXStatusCell *cell = [XXStatusCell cellWithTableView:tableView]; //设置数据 cell.status = self.statuses[indexPath.row]; return cell;}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { XXStatus *status = self.statuses[indexPath.row]; return status.cellHeight;}
2、storyboard方式自定义非等高cell
用storyboard和xib其实大同小异,直接在storyboard中添加子控件并添加约束,设置重用标识,修改cell的类,修改cell为动态创建类型。注意,如果Lable要显示多行的话,Lines要改为0,而且cell高度极端准确,要加一个方法:
- (void)awakeFromNib { self.contentLable.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;}
然后获取cell时直接在缓存池中根据重用标识去查找,其他的和xib方式一样。
+ (instancetype)cellWithTableView :(UITableView *)tableView { return [tableView dequeueReusableCellWithIdentifier:@"status"]; }