前面已經詳細介紹了在不使用Masonry的情況下動態生成標準MVC下生成動態生成UICollectionViewCell的size。地址如下:
標準MVC下動態生成UICollectionViewCell的size(View內完成)
標準MVC下動態生成UICollectionViewCell的size(Controller內完成)
大家看完之后肯定會覺得有點麻煩,畢竟Cell內可能會添加許多view,使用上述方法需要計算每一個View的frame,然后再計算cell的size并且返回。 那么有么有更簡單的辦法呢? 有!那就是使用Masonry。
Masonry的簡單用法可以搜相關教程,這里不再贅述。不過推薦標哥的博客,寫的很詳細:
標哥的技術博客,Masonry講解
Demo很簡單,效果圖如下:
具體實現方法如下:
首先自定義一個UICollectionViewCell:
#import <UIKit/UIKit.h>
@interface LCHCollectionViewCell : UICollectionViewCell
@property (nonatomic, strong) UILabel *firstLabel;
@property (nonatomic, strong) UILabel *secondLabel;
@end
然后在initWithFrame:內添加這兩本label:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_firstLabel = [[UILabel alloc] init];
_firstLabel.numberOfLines = 1;
_firstLabel.textAlignment = NSTextAlignmentCenter;
_firstLabel.backgroundColor = [UIColor redColor];
_firstLabel.font = [UIFont systemFontOfSize:25];
_secondLabel = [[UILabel alloc] init];
_secondLabel.numberOfLines = 1;
_secondLabel.textAlignment = NSTextAlignmentCenter;
_secondLabel.backgroundColor = [UIColor greenColor];
_secondLabel.font = [UIFont systemFontOfSize:25];
[self.contentView addSubview:_firstLabel];
[self.contentView addSubview:_secondLabel];
self.backgroundColor = [UIColor blackColor];
}
return self;
}
然后重寫layoutSubviews方法,給其子View添加約束:
- (void)layoutSubviews {
[super layoutSubviews];
__weak typeof(self) weakSelf = self;
[self.firstLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(weakSelf.contentView);
make.left.equalTo(weakSelf.contentView);
make.width.greaterThanOrEqualTo(@0.1);
make.height.greaterThanOrEqualTo(@0.1);
make.height.equalTo(weakSelf.contentView).priorityLow();
}];
[self.secondLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(weakSelf.contentView);
make.left.mas_equalTo(weakSelf.firstLabel.mas_right);
make.width.greaterThanOrEqualTo(@0.1);
make.height.greaterThanOrEqualTo(@0.1);
make.right.equalTo(weakSelf.contentView).priorityLow();
make.height.equalTo(weakSelf.contentView).priorityLow();
}];
}
Controller內UICollectionView的初始化代碼如下:
- (UICollectionView *)collectionView {
if (_collectionView) {
return _collectionView;
}
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 5;
layout.minimumInteritemSpacing = 5;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);
layout.estimatedItemSize = CGSizeMake(80, 50);
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, self.view.center.y, self.view.frame.size.width, self.view.frame.size.height/15) collectionViewLayout:layout];
_collectionView.dataSource = self;
_collectionView.delegate = self;
_collectionView.backgroundColor = [UIColor yellowColor];
[_collectionView registerClass:[LCHCollectionViewCell class] forCellWithReuseIdentifier:@"reuse"];
return _collectionView;
}
其中一定要給cell一個預估的size,如果沒有的話顯示不正確。
layout.estimatedItemSize = CGSizeMake(80, 50);
然后在UICollectionViewDelegateFlowLayout協議中實現
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeZero;
}
這個方法返回cell的size。這個方法必須實現,否則會報錯,返回值為可以任意設置,都不會對顯示造成影響,但是當設置的值與collectionView沖突的時候回報錯,因此推薦返回CGSizeZero。
當然需要在UICollectionViewDataSource協議中根據model的屬性設置view需要顯示的內容:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
LCHCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"reuse" forIndexPath:indexPath];
LCHModel *model = self.models[indexPath.row];
cell.firstLabel.text = model.firstString;
cell.secondLabel.text = model.secondString;
[cell layoutIfNeeded];
return cell;
}
其余就不需要其他操作了,是不是覺得很神奇! 無需繁瑣的計算,自動生成cell的size。