UI基础 - UITableView 02:单元格定制 | 自适应高度
■ 单元格定制
1. 系统的 UITableViewCell 通常不能满足自身的 UI 设计效果,那么一般有两条路可走
要么是修改系统自身的 cell
要么是使用 UITableViewCell 的子类
2. 代码示例:实现单元格定制
方式一:在控制器中当 cell 创建时直接修改
// - ViewController
1 #import "ViewController.h" 2 @interface ViewController ()<UITableViewDataSource,UITableViewDelegate>// 接受协议 3 4 @end 5 6 @implementation ViewController 7 8 - (void)viewDidLoad { 9 [super viewDidLoad]; 10 self.view.backgroundColor = [UIColor cyanColor]; 11 12 self.navigationItem.title = @"cell定制"; 13 14 UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0,self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain]; 15 tableView.separatorColor = [UIColor blueColor]; 16 tableView.dataSource = self; 17 tableView.delegate = self; 18 [self.view addSubview:tableView]; 19 } 20 21 #pragma mark - <UITableViewDataSource> 22 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 23 switch (section) { 24 case 0:return 3; 25 case 1:return 5; 26 case 2:return 8; 27 } 28 return 0; 29 } 30 31 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 32 return 3; 33 } 34 35 // cell 36 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 37 38 static NSString * cellIndentifier = @"cell"; 39 UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIndentifier]; 40 41 // cell 定制:cell 初始化一定要在创建时进行 42 if (!cell) { 43 44 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIndentifier]; 45 46 // 右按钮 47 UIButton *rightBT = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 48 rightBT.frame = CGRectMake(220, 10, 100, 30); 49 [rightBT setTitle:@"right" forState:UIControlStateNormal]; 50 [cell.contentView addSubview:rightBT]; 51 52 // 左标提 53 UILabel *leftLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 30)]; 54 leftLabel.tag = 103;// 赋值使用 55 leftLabel.backgroundColor = [UIColor redColor]; 56 [cell.contentView addSubview:leftLabel]; 57 } 58 59 // 左标题赋值 60 UILabel *leftLab = (UILabel*)[cell.contentView viewWithTag:103];// 获取到 Label 61 leftLab.text = [NSString stringWithFormat:@"%ld",indexPath.row];// 赋值 62 63 return cell; 64 } 65 66 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 67 68 return [[NSArray arrayWithObjects:@"-A-",@"-B-",@"-C-",nil] objectAtIndex:section]; 69 } 70 71 72 - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{ 73 74 return @[@"A",@"B",@"C"]; 75 } 76 77 #pragma mark - <UITableViewDelegate> 78 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 79 80 return 10; 81 } 82 83 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 84 85 return 50; 86 } 87 88 @end
运行效果
方式二:在控制器中直接修改单元格会使代码冗余且分散!接下来我们使用 UITableViewCell 的子类实现单元格定制,降低代码耦合度,并对其做自适应高度处理
// - MakeCell.h
1 #import <UIKit/UIKit.h> 2 #define W_Text [UIScreen mainScreen].bounds.size.width - 20 3 @interface MakeCell : UITableViewCell 4 @property(nonatomic,strong)UILabel *contenLabel;// 文本内容 5 6 @end
// - MakeCell.m
1 #import "MakeCell.h" 2 @implementation MakeCell 3 4 - (void)awakeFromNib { 5 [super awakeFromNib]; 6 } 7 8 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 9 [super setSelected:selected animated:animated]; 10 } 11 12 // 重写方法:在里面初始化控件 13 -(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ 14 15 self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 16 if (self) { 17 18 self.contenLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, W_Text, 60)]; 19 self.contenLabel.backgroundColor = [UIColor orangeColor]; 20 self.contenLabel.font = [UIFont systemFontOfSize:15.0]; 21 self.contenLabel.numberOfLines = 0;// 不限行 22 self.contenLabel.lineBreakMode = NSLineBreakByWordWrapping; 23 [self.contentView addSubview:self.contenLabel]; 24 25 self.contentView.backgroundColor = [UIColor cyanColor]; 26 27 } 28 return self; 29 } 30 31 // 高度自适应:步骤一 32 // 在 layoutSubviews 处理自适应,减少 VC 中的代码量 33 -(void)layoutSubviews{ 34 [super layoutSubviews]; 35 36 /* 自适应高度步骤 37 * 1、字号和换行模式,要保持一致 38 * 2、高度自适应实际上是指定宽度且高度足够大 39 */ 40 NSString *text = self.contenLabel.text; 41 // 宽度 300,高度管够 42 CGSize textSize = [text sizeWithFont:[UIFont systemFontOfSize:15.0] constrainedToSize:CGSizeMake(W_Text, 10000) lineBreakMode:NSLineBreakByWordWrapping]; 43 CGRect rect = self.contenLabel.frame; 44 rect.size.height = textSize.height; 45 self.contenLabel.frame = rect; 46 } 47 @end
// - ViewController.h
1 #import "ViewController.h" 2 #import "MakeCell.h" 3 @interface ViewController ()<UITableViewDataSource,UITableViewDelegate> 4 @property(nonatomic,strong)NSArray *dataArray;// 数据源 5 6 @end 7 8 @implementation ViewController 9 10 - (void)viewDidLoad { 11 [super viewDidLoad]; 12 self.navigationItem.title = @"高度自适应"; 13 14 // 数据源 15 self.dataArray = [NSArray arrayWithObjects:@"姆大陆土地辽阔,东起现今夏威夷群岛,西至马里亚纳群岛,南边是斐济、大溪地群岛和复活节岛,全大陆东西长8000公里,南北宽5000公里,相当于南北美洲面积的总和,总面积约为3500万平方公里,是一块美丽富饶的地方。今天的人类文明中不可解释的一些现象可能来自于姆大陆人的文明。", 16 @"雷姆利亚大陆的传说地理位置在今天的印度洋。根据地质学家的推测,雷姆利亚大陆应该是在距今约3400万年前(即第三纪初期)开始沉没的,在约2500万年前完全沉没。", 17 @"在柏拉图的提示中,有这样的话:“在梭伦九千年前左右,海格力斯之柱(直布罗陀海峡)对面,有一个很大的岛,从那里你们可以去其它的岛屿,那些岛屿的对面,就是海洋包围着的一整块陆地,这就是‘亚特兰蒂斯’王国”。当时亚特兰蒂斯正要与雅典展开一场大战,没想到亚特兰蒂斯却突然遭遇到地震和水灾,不到一天一夜就完全没入海底,成为希腊人海路远行的阻碍。", 18 @"黄金国(西班牙文:El Dorado,意思为“The Golden One”)别称黄金城、黄金乡,为一个古老传说,最早是始于一个南美仪式,部落族长会在自己的全身涂满金粉,并到山中的圣湖中洗净,而祭司和贵族会将珍贵的黄金和绿宝石投入湖中献给神。", 19 @"阿瓦隆(Avalon)是亚瑟王传说中的重要岛屿,凯尔特神话的圣地,古老德鲁伊宗教的中心信仰", 20 @"Bermeja岛:古老的地图上常常出现无法找到的岛屿和大陆板块。其中一些所谓“幽灵岛屿”是由于早期的地理变化而消失,其它的岛屿就像Bermeja一样被认为事实上曾经存在并且由于自然灾难而消失了。古老地图上将Bermeja标记在墨西哥湾,在墨西哥尤卡坦半岛西北100英里的位置。",nil]; 21 22 self.view.backgroundColor = [UIColor whiteColor]; 23 UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height-64) style:UITableViewStylePlain]; 24 tableView.separatorColor = [UIColor blueColor]; 25 tableView.dataSource = self; 26 tableView.delegate = self; 27 [self.view addSubview:tableView]; 28 } 29 30 #pragma mark - <UITableViewDataSource> 31 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 32 33 return self.dataArray.count; 34 } 35 36 // cell 37 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 38 39 static NSString *cellIndentifier = @"cell"; 40 MakeCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIndentifier]; 41 if (!cell) { 42 // 初始化 43 cell = [[MakeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIndentifier]; 44 } 45 46 NSString *text = [self.dataArray objectAtIndex:indexPath.row]; 47 cell.contenLabel.text = text; 48 49 // // 高度自适应:步骤一 50 // // 可优化:把此处代码搬进 layoutSubviews 中处理 51 // CGSize textSize = [text sizeWithFont:[UIFont systemFontOfSize:15.0] constrainedToSize:CGSizeMake(W_Text, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping]; 52 // CGRect rect = cell.contenLabel.frame; 53 // rect.size.height = textSize.height; 54 // cell.contenLabel.frame = rect; 55 56 return cell; 57 } 58 59 #pragma mark - <UITableViewDelegate> 60 // 高度自适应:步骤二 61 // cell 自适应高度完成后,在代理方法中同样要返回相对应的高度 62 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 63 64 NSString *text = [self.dataArray objectAtIndex:indexPath.row]; 65 CGSize textSize = [text sizeWithFont:[UIFont systemFontOfSize:15.0] constrainedToSize:CGSizeMake(W_Text, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping]; 66 return textSize.height + 20; 67 } 68 69 @end
运行效果