iOS学习31之UITableVIewCell自定义
1. 自定义Cell
1> 为什么要自定义Cell
- UITableView 中系统的Cell共提供了四种默认样式, 分别是:
UITableViewCellStyleDefault
UITableViewCellStyleValue1
UITableViewCellStyleValue2
UITableViewCellStyleSubtitle
但是在实际使用过程中, Cell样式的布局上千差万别, 因此我们需要自定义Cell
-
在前期我们学过自定义视图, 即创建一个类继承于 UIView 或者 其他的视图, 在自定义类中创建其子视图, 这样就会形成一个新的自定义视图。
-
系统提供的cell满足不了复杂的样式,因此: 定义Cell和自定义视图一样,自己创建一种符合我们需求的Cell并使用这个Cell。
2> 自定义Cell的步骤
-
创建一个类继承于 UITableViewCell
-
实现 UITableViewCell 的初始化方法:
1 // 初始化 2 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 3 self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 4 if (self) { 5 //初始化子视图 6 [self initLayout]; 7 } 8 return self; 9 } 10 11 //初始化子视图布局方法 12 - (void)initLayout { 13 14 //1.头像 15 self.headerImageView = [[UIImageView alloc]initWithFrame:CGRectMake(16, 10, 100, 100)]; 16 17 self.headerImageView.layer.masksToBounds = YES; 18 19 self.headerImageView.layer.cornerRadius = CGRectGetWidth(self.headerImageView.frame) / 2; 20 21 // cell提供一个contactVIew属性,专门用来自定义cell,防止在cell布局的时候发生布局混乱,如果是自定义cell,记得将子控件添加到contactVIew上 22 [self.contentView addSubview:self.headerImageView]; 23 24 //2.姓名 25 self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.headerImageView.frame) + 10, CGRectGetMinY(self.headerImageView.frame), 100, 40)]; 26 27 [self.contentView addSubview:self.nameLabel]; 28 29 //3.电话号码 30 self.phoneLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMinX(self.nameLabel.frame), CGRectGetMaxY(self.nameLabel.frame) + 20, 200, 40)]; 31 32 [self.contentView addSubview:self.phoneLabel]; 33 }
contentView 是 Cell 提供一个属性,专门用来自定义 Cell ,防止在 Cell 布局的时候发生布局混乱,如果是自定义 Cell,记得将子控件添加到 contactVIew 上
效果图:
- 确保所有的你想添加的子视图都在自定义 Cell 的初始化方法中创建, 由于 UITableView 的重用机制, 一个 Cell 在第一次创建成功并用于下一次显示的时候,不会再走初始化方法, 这样可以避免子视图的重复创建。
-
在 Cell 的子视图创建成功后,将子视图设置为属性,类似于 UITableViewCell 所自带的 textLabel 和 detailTextLabel 属性。便于在 UITableView 的协议中给自定义视图赋值。
2. 多种Cell混合使用
1> 概述
在 TableView 中不仅仅只显示一种 Cell , 多种 Cell 可以并存
2> 使用场景
一个重用标识符只能针对于一种 Cell 样式, 不同的 Cell 需要基于不同的重用标识符来进行区分, 重用标识符的区分需要根据不同的情况来划分, 如:
- model 属性划分(不同的数据内容,比如一个数据中有 type 字段, 为1代表图片类型, 为0代表文字类型)
1 Model *model = [self.tableArray objectAtIndex:indexPath.row]; 2 //根据model属性划分 3 if (model.type == 0) { 4 FirstTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:firstIdentify]; 5 return cell; 6 } 7 if (model.type == 1) { 8 SecondTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:secondIdentify]; 9 return cell; 10 }
- 固定的行显示的 Cell 类型不一样
1 // 第一行显示第一种Cell 2 if (indexPath.row == 0) { 3 FirstTableViewCell *cell = [tableView 4 dequeueReusableCellWithIdentifier:firstIdentify]; 5 return cell; 6 } 7 // 第二行显示第二种Cell 8 if (indexPath.row == 1) { 9 SecondTableViewCell *cell = [tableView 10 dequeueReusableCellWithIdentifier:secondIdentify]; 11 return cell; 12 }
3. Cell自适应高度
1> 自适应高度的两种应用
① 文本自适应高度:根据文本内容设定Label高度
第一步: 修改 Label 的高度(在 - (void)layoutSubView 方法中 )
1 - (void)layoutSubviews { 2 3 // 1. 获取文本高度 4 CGFloat textHeight = [Tool textHeightWithText:self.myLabel.text font:[UIFont systemFontOfSize:20]]; 5 // 2.修改label的frame 6 self.myLabel.frame = CGRectMake(0, 0, self.bounds.size.width, textHeight); 7 }
获取文本高度的方法(一般封装在工具类中)
1 // 计算文本高度 2 + (CGFloat)textHeightWithText:(NSString *)text font:(UIFont *)font { 3 4 // iOS7.0中求文本高度的方法,返回一个CGRect的高度 5 6 // 第一个参数 7 CGSize size = CGSizeMake([UIScreen mainScreen].bounds.size.width, 10000); 8 9 // 第二个参数:设置以行高为单位 10 CGRect rect = [text boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil]; 11 12 return rect.size.height; 13 }
第二步:设置 Cell 的高度
1 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 2 3 CGFloat textHeight = [Tool textHeightWithText:self.myModel.textString font:[UIFont systemFontOfSize:20]]; 4 5 return textHeight; 6 }
② 图片自适应高度:根据图片宽度进行等比例缩放
第一步:修改imageView的高度
1 - (void)layoutSubviews { 2 // 1.获取图片的高度 3 CGFloat imageH = [Tool imageHeightWithImage:self.myImageView.image]; 4 // 2.修改imageView的高度 5 self.myImageView.frame = CGRectMake(0, textHeight, [UIScreen mainScreen].bounds.size.width, imageH); 6 }
获取图片高度的方法(一般封装在工具类中)
1 + (CGFloat)imageHeightWithImage:(UIImage *)image { 2 3 // 获取图片的宽度和高度 4 CGFloat width = image.size.width; 5 CGFloat height = image.size.height; 6 // 计算图片高度 7 float scile = height / width; 8 float screenH = [UIScreen mainScreen].bounds.size.width; 9 10 return scile * screenH; 11 }
第二步:设置 Cell 的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat imageHeight = [Tool imageHeightWithImage:self.myModel.image]; return imageHeight; }
在上面 获取图片高度的方法 中存在一个 bug , 当计算图片高度的数据类型为CGFloat时, 对于某些图片就会出现程序崩溃
错误代码:
1 + (CGFloat)imageHeightWithImage:(UIImage *)image { 2 3 // 获取图片的宽度和高度 4 CGFloat width = image.size.width; 5 CGFloat height = image.size.height; 6 // 计算图片高度 7 CGFloat scile = height / width; 8 CGFloat screenH = [UIScreen mainScreen].bounds.size.width; 9 10 return scile * screenH; 11 }
错误信息:
③ 两种使用同时出现
其他部分全部相同,处理在第二步设置Cell的高度, 代码如下:
1 // 设置cell的高度 2 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 3 // 得到文字自适应高度 4 CGFloat textHeight = [Tool textHeightWithText:self.myModel.textString font:[UIFont systemFontOfSize:20]]; 5 // 得到图片自适应高度 6 CGFloat imageHeight = [Tool imageHeightWithImage:self.myModel.image]; 7 // 返回两者的和 8 return textHeight + imageHeight; 9 }