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 的大小,從而計算出滾動條的長度。所以這樣的性能不好,所以蘋果推出了