前面已经详细介绍了在不使用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。