每一個有使用列表 App 都會用到 UITableView
或 UICollectionView
探越,這就意味著也會用到 UITableViewCell
或 UICollectionViewCell
向叉。因為 UITableView
和 UICollectionView
不是靜止不動的挚歧,在與用戶交互過程中假哎,需要通過不斷地滾動來更新數(shù)據(jù),而更新數(shù)據(jù)的展示就需要通過更新 UITableViewCell
和 UICollectionViewCell
的展示數(shù)據(jù)险绘。
以 UITableViewCell
為例换可,UITableViewCell
自帶一個 UIImageView
和兩個 UILabel
,但是這些控件的布局是由 UITableViewCellStyle
決定的奠旺,使用 setFrame:
也是沒有效果蜘澜。顯然只有這三個控件和固定的幾種樣式,是滿足不了大多數(shù)產(chǎn)品需求和美工設(shè)計的响疚。這個時候鄙信,我們就會想到使用復合視圖的方式來實現(xiàn)設(shè)計需求,即在 UITableViewCell
的基礎(chǔ)上添加新的視圖控件忿晕。
然而装诡,使用復合視圖并不是一個好的方案,這就意味著將增加了視圖層次結(jié)構(gòu)的嵌套層次。雖然視圖層次的多層嵌套是難免的鸦采,也是必要的宾巍,但是深層次的嵌套結(jié)構(gòu)勢必影響性能。因為當父視圖更新布局時渔伯,就會觸發(fā) setNeedsLayout:
方法顶霞,而當這個方法被觸發(fā)時也會觸發(fā) layoutSubviews:
方法去更新所有子視圖的布局。所以我們應當避免在視圖層次結(jié)構(gòu)中多層嵌套咱旱,盡量保持扁平化确丢。
那么問題來了,不用復合視圖要怎么解決復雜的列表設(shè)計呢吐限?
那就在一個視圖控件上實現(xiàn)要多個視圖控件才能做到的事情鲜侥。我們使用重寫 UIView
的 drawRect:
方法來自定義渲染元素,將需要顯示的圖片和文字直接繪制到一張視圖上诸典。
自定義 UITableViewCell
的頭文件 ImproveTableViewCell.h
:
/**
繪制 cell
*/
@interface ImproveTableViewCell : UITableViewCell
/**
標題
*/
@property (nonatomic, copy) NSString *strTitle;
/**
圖片組
*/
@property (nonatomic, copy) NSArray<NSString *> *arrImage;
/**
日期
*/
@property (nonatomic, copy) NSString *strDate;
@end
實現(xiàn)文件 ImproveTableViewCell.m
:
@implementation ImproveTableViewCell
/**
重寫視圖方法繪制
@param rect 坐標大小
*/
- (void)drawRect:(CGRect)rect {
// 屏幕寬
CGFloat fScreenWidth = [[UIScreen mainScreen] bounds].size.width;
// 文本屬性
NSDictionary *dicAttribute;
// 標題
dicAttribute = @{NSFontAttributeName: [UIFont systemFontOfSize:14], NSForegroundColorAttributeName: [UIColor colorWithWhite:0.2 alpha:1.0]};
[self.strTitle drawInRect:CGRectMake(10, 10, fScreenWidth - 20, 20) withAttributes:dicAttribute];
// 圖片組
// 圖片寬
CGFloat fImageWidth = (fScreenWidth - 40)/3;
for (int i = 0; i < 3; i++) {
UIImage *imgPicture = [UIImage imageNamed:self.arrImage[i]];
[imgPicture drawInRect:CGRectMake(10 + i * (fImageWidth + 10), 40, fImageWidth, fImageWidth * 3/4)];
}
// 日期
dicAttribute = @{NSFontAttributeName: [UIFont systemFontOfSize:13], NSForegroundColorAttributeName: [UIColor colorWithWhite:0.6 alpha:1.0]};
[self.strDate drawInRect:CGRectMake(10, 45 + fImageWidth * 3/4, fScreenWidth - 20, 20) withAttributes:dicAttribute];
// 分割線
[[UIColor colorWithWhite:0.9 alpha:1.0] set];
UIRectFill(CGRectMake(0, 65 + fImageWidth * 3/4, fScreenWidth, 5));
}
@end
UITableViewDelegate
和 UITableViewDataSource
的方法實現(xiàn):
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
ImproveTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:gDrawID];
if (cell == nil) {
cell = [[ImproveTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:gDrawID];
}
cell.strTitle = indexPath.row%2 ? @"蠟筆小新--lol船長" : @"葛力姆喬·賈卡杰克";
cell.arrImage = indexPath.row%2 ? @[@"test1", @"test2", @"test1"] : @[@"test2", @"test1", @"test2"];
cell.strDate = indexPath.row%2 ? @"2018-03-30 大傻逼" : @"2018-03-31 小傻逼";
// 更新渲染
[cell setNeedsDisplay];
return cell;
}
- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 100;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return ([[UIScreen mainScreen] bounds].size.width - 40)/4 + 70;
}
結(jié)果截圖:
參考資料:《高性能 iOS 應用開發(fā)》