iOS学习之 UITableVIew cell 创建方式(XIB
UITableView
-
数据源的常用方法
-
此方法设置 cell 的组数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
-
每一组有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
-
每一行显示什么内容,返回 cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
-
设置每一组的头部信息
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
-
设置每一组的尾部信息
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
-
tabelView常见属性
// 设置每一行cell的高度 self.tableView.rowHeight = 100; // 设置每一组头部的高度 self.tableView.sectionHeaderHeight = 50; // 设置每一组尾部的高度 self.tableView.sectionFooterHeight = 50; // 设置分割线颜色 self.tableView.separatorColor = [UIColor redColor]; // 设置分割线样式 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 设置表头控件 self.tableView.tableHeaderView = [[UISwitch alloc] init]; // 设置表尾控件 self.tableView.tableFooterView = [UIButton buttonWithType:UIButtonTypeContactAdd]; // 设置右边索引文字的颜色 self.tableView.sectionIndexColor = [UIColor redColor]; // 设置右边索引文字的背景色 self.tableView.sectionIndexBackgroundColor = [UIColor blackColor];
-
cell
-
UITableView的每一行都是一个UITableViewCell,通过dataSource的tableView:cellForRowAtIndexPath:方法来初始化每一行
-
UITableViewCell内部有个默认的子视图:contentView,contentView是UITableViewCell所显示内容的父视图,可显示一些辅助指示视图
-
辅助指示视图的作用是显示一个表示动作的图标,可以通过设置UITableViewCell的accessoryType来显示,默认是UITableViewCellAccessoryNone(不显示辅助指示视图)
-
可以通过cell的accessoryView属性来自定义辅助指示视图(比如往右边放一个开关)
-
传统的写法
/** * 每当有一个cell要进入视野范围内,就会调用一次 */ - (UITableViewCell *)tableView:(UITableView *)tableView cell ForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"wine"; // 1.先去缓存池中查找可循环利用的cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; // 2.如果缓存池中没有可循环利用的cell if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } // 3.设置数据 cell.textLabel.text = [NSString stringWithFormat:@"%zd行的数据", indexPath.row]; return cell;
}
```
-
新的写法(注册cell)
NSString *ID = @"wine"; - (void)viewDidLoad { [super viewDidLoad]; // 注册某个重用标识 对应的 Cell类型 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.先去缓存池中查找可循环利用的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 2.设置数据
cell.textLabel.text = [NSString stringWithFormat:@"%zd行的数据", indexPath.row];
return cell;
}
```
-
自定义 cell
-
等高 cell 代码
- 新建一个继承自
UITableViewCell
的子类 - 重写新建子类的
-initWithStyle:reuseIdentifier:
方法在这个方法中添加所有需要显示的子控件。给子控件做一些初始化设置(设置字体、文字颜色等) - 重写
-layoutSubviews
方法一定要调用[superlayoutSubviews]
在这个方法中计算和设置所有子控件的frame - 提供模型属性,设置模型的数据,在 set 方法中
- 注册 cell。。。下面方法是从 xib 中 zuce
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([MTTgCell class]) bundle:nil] forCellReuseIdentifier:ID];
- 新建一个继承自
-
不等高 cell
- 在模型内部提供可设置 cell高度 的的 frame属性,
@interface XMGStatus : NSObject @property (nonatomic, assign) CGRect iconFrame; /** cell的高度 */ @property (nonatomic, assign) CGFloat cellHeight; @end
-
在
model.m
中重写模型cellHeight属性的get方法- (CGFloat)cellHeight { if (_cellHeight == 0) { // ... 计算所有子控件的frame、cell的高度 } return _cellHeight; }
-
在控制器中实现返回 cell 高度的代理方法,heightforrow
// 返回每一行cell的具体高度 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { SBStatus *status = self.statuses[indexPath.row]; return status.cellHeight; }
-
给 cell 模型传值
-
新建一个继承自
UITableViewCell
的子类,比如SBStatusCell,并且提供一个模型属性 -
在SBStatusCell.m中重写模型属性的set方法
-
文字尺寸的计算
- 计算文字所占据的尺寸
NSDictionary *nameAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:17]}; CGSize nameSize = [self.name sizeWithAttributes:nameAttrs];
- 计算一段文字的尺寸
CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT); NSDictionary *textAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:14]}; CGFloat textH = [self.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textAttrs context:nil].size.height;
- 计算屏幕的宽
[UIScreen mainScreen].bounds.size.width
- 连线修改约束
- 定义一个高度约束且连线到 storyboard
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *picHeight;
- 然后在模型设置控件的 set 方法中修改
self.picHeight.constant = 100;
- 定义一个高度约束且连线到 storyboard
- cellheight 不等高的估算和自动计算
- 程序一开始就会吧 tabelViewl 的所有cell高度算出来,确定 contengSize 的大小,从而计算出滚动条的长度。所以这样的性能不好,所以苹果推出了
估算高度
。 - 告诉tabelview的 cell的估算高度,就可以使heightforrow方法的调用次数减少
- 设置估算的方法
self.tabelView.estimateRowHeight = 10
-
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
通过代理方法
- 处理不等高 cell 自动计算(iOS8开始才支持)
- 告诉tableView所有cell的真实高度是自动计算(根据设置的约束来计算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
- 告诉tableView所有cell的估算高度.
self.tableView.estimatedRowHeight = 44;
- 这种需要设置约束连线,然后在 cell 的 setModel 方法中进行判断
// 设置配图数据 if (status.picture) { // 有配图 self.pictureHeight.constant = 100; self.pictureBottom.constant = 10; self.pictureImageView.image = [UIImage imageNamed:status.picture]; } else { // 没有配图 // 设置图片高度为0 self.pictureHeight.constant = 0; // 设置图片底部间距为0 self.pictureBottom.constant = 0;
- 告诉tableView所有cell的真实高度是自动计算(根据设置的约束来计算)
```-
iOS 8之前
- 如果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的高度
XMGStatusCell *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; } ``` 4. 在 cell.m中设置 height 高度
- (CGFloat)height { // 强制布局cell内部的所有子控件(label根据文字多少计算出自己最真实的尺寸) [self layoutIfNeeded]; // 计算cell的高度 if (self.status.picture) { return CGRectGetMaxY(self.pictureImageView.frame) + 10; } else { return CGRectGetMaxY(self.text_label.frame) + 10; } }
- 程序一开始就会吧 tabelViewl 的所有cell高度算出来,确定 contengSize 的大小,从而计算出滚动条的长度。所以这样的性能不好,所以苹果推出了