說到iOS
自動佈局,有不少的解決辦法。有的人使用xib/storyboard
自動佈局,也有人使用frame
來適配。對於前者,筆者並不喜歡,也不支持。對於後者,更是麻煩,處處計算高度、寬度等,千萬大量代碼的冗餘,對維護和開發的效率都很低。git
筆者在這裏介紹純代碼自動佈局的第三方庫:Masonry
。這個庫使用率至關高,在全世界都有大量的開發者在使用,其star
數量也是至關高的。github
本節詳解Masonry
的以動畫的形式更新約束的基本用法,先看看效果圖:佈局
咱們這裏初始按鈕是一個很小的按鈕,點擊就不斷放大,最大就放大到全屏幕。測試
看下代碼:動畫
#import "TableViewController.h" #import "TestCell.h" @interface TableViewController () <UITableViewDataSource, UITableViewDelegate> @property (nonatomic, strong) UITableView *tableView; @property (nonatomic, strong) NSMutableArray *dataSource; @end @implementation TableViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView = [[UITableView alloc] init]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.tableView.delegate = self; self.tableView.dataSource = self; [self.view addSubview:self.tableView]; [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); }]; for (NSUInteger i = 0; i < 10; ++i) { TestModel *model = [[TestModel alloc] init]; model.title = @"測試標題,可能很長很長,反正隨便寫着先吧!"; model.desc = @"描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,描述內容一般都是很長很長的,"; [self.dataSource addObject:model]; } [self.tableView reloadData]; } - (NSMutableArray *)dataSource { if (_dataSource == nil) { _dataSource = [[NSMutableArray alloc] init]; } return _dataSource; } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataSource.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @"CellIdentifier"; TestCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (!cell) { cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; } cell.indexPath = indexPath; cell.block = ^(NSIndexPath *path) { [tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationFade]; }; TestModel *model = [self.dataSource objectAtIndex:indexPath.row]; [cell configCellWithModel:model]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { TestModel *model = [self.dataSource objectAtIndex:indexPath.row]; return [TestCell heightWithModel:model]; } @end
咱們來看看這個計算行高的代碼,看起來是否是很像配置數據的代理方法呢?atom
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { TestModel *model = [self.dataSource objectAtIndex:indexPath.row]; return [TestCell heightWithModel:model]; }
咱們看看TestCell
的聲明,提供了一個計算行高的類方法:spa
typedef void (^TestBlock)(NSIndexPath *indexPath); @interface TestCell : UITableViewCell @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UILabel *descLabel; @property (nonatomic, strong) NSIndexPath *indexPath; @property (nonatomic, copy) TestBlock block; - (void)configCellWithModel:(TestModel *)model; + (CGFloat)heightWithModel:(TestModel *)model; @end
咱們看一下計算行高的實現:代理
+ (CGFloat)heightWithModel:(TestModel *)model { TestCell *cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@""]; [cell configCellWithModel:model]; [cell layoutIfNeeded]; CGRect frame = cell.descLabel.frame; return frame.origin.y + frame.size.height + 20; }
咱們只是建立了一個cell
而後配置數據,而後調用layoutIfNeeded
更新約束,以便獲取到frame
。當咱們獲取到之後,咱們就能夠計算出最後的cell
真正的高度了。code
關於計算cell
的行高,筆者開源了一個擴展類,固然在公司內部也是你們都在使用的,能夠減小大量的代碼。若是須要使用,能夠到這裏下載:https://github.com/CoderJackyHuang/HYBMasonryAutoCellHeight或者直接使用cocoapods
安裝。blog
你們能夠到筆者的github
下載源代碼:MasonryDemo
舒適提示:本節所講內容對應於TableViewController
中的內容