iOS 【使用CollectionView瀑布流佈局】
阿新 • • 發佈:2019-02-19
CollectionView是iOS 6引入的控制元件,今天的重點並不是介紹它,而是使用它進行佈局。效果圖如下:
兩列效果圖.png
三列效果圖.png
看了效果圖,再來說說具體的實現步驟:
1.新增CollectionView控制元件
[self.view addSubview:self.myCollectionView];
2.載入資料(在[self addData]
方法中進行資料的處理)
self.myCVLayout.dataArr = [self addData];
3.對CollectionView進行配置(懶載入)[1]
_myCollectionView = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:self.myCVLayout];
_myCollectionView.backgroundColor = [UIColor orangeColor];
[_myCollectionView registerNib:[UINib nibWithNibName:@"MyCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:CVCell];
_myCollectionView.dataSource = self;
4.對約束layout進行配置(懶載入)
_myCVLayout = [[CollectionLayout alloc]initOptionWithColumnNum:2 rowSpacing:10.0f columnSpacing:10.0f sectionInset:UIEdgeInsetsMake(20, 10, 10, 10)];
5.配置CollectionView的dataSource方法
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.myCVLayout .dataArr.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:CVCell forIndexPath:indexPath];
cell.image.image = [UIImage imageNamed:self.myCVLayout.dataArr[indexPath.row]];
return cell;
}
6.建立一個UICollectionViewLayout的類,並結合第3步CollectionView的配置進行配置
if (self = [super init]) {
_columnNum = columnNum;
_rowSpacing = rowSpacing;
_columnSpacing = columnSpacing;
_sectionInset = sectionInset;
_everyColumnHDict = [NSMutableDictionary dictionary];
_attributeArr = [NSMutableArray array];
}
7.計算圖片顯示的高度
NSString * imageName = _dataArr[i];
UIImage * image = [UIImage imageNamed:imageName];
CGFloat imageH = image.size.height / image.size.width * width;
return imageH;
8.重寫prepareLayout方法[2]
for (int i = 0; i < _columnNum; i++) {
[_everyColumnHDict setObject:@(_sectionInset.top) forKey:[NSString stringWithFormat:@"%d",i]];
}
for (int i = 0; i < _dataArr.count; i++) {
[_attributeArr addObject:[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]];
}
9.重寫layoutAttributesForItemAtIndexPath方法
//建立一個約束
UICollectionViewLayoutAttributes * attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//計算寬度(等寬)
CGFloat itemW = (self.collectionView.bounds.size.width - _sectionInset.left - _sectionInset.right - (_columnNum - 1) * _rowSpacing) / _columnNum;
//根據寬度算高度
CGFloat itemH = [self calculateImageHeightWithCount:indexPath.row withWidth:itemW];
//確定了寬度和高度
CGRect frame = CGRectMake(0, 0, itemW, itemH);
//x代表第幾列,y是origin的y
NSInteger x = 0;
CGFloat y = 0.0f;
//遍歷字典即檢視每一列的高度,確定最短的一列(x為第幾列,y是高度)
for (id temKey in _everyColumnHDict) {
CGFloat temHeight = [_everyColumnHDict[temKey] floatValue];
if (y == 0) {
y = temHeight;
x = [temKey integerValue];
continue;
}
if(y > temHeight ) {
y = temHeight;
x = [temKey integerValue];
}
}
//設定frame的origin
frame.origin = CGPointMake(_sectionInset.left + x * (itemW + _rowSpacing), y);
//將這一列最新的高度儲存下來,字典會自動覆蓋原來的資料
NSString * key = [NSString stringWithFormat:@"%ld",x];
NSNumber * height = @(_columnSpacing + y + itemH);
[_everyColumnHDict setObject:height forKey:key];
//設定並返回約束
attribute.frame = frame;
return attribute;
10.重寫collectionViewContentSize方法(設定可滾動的範圍)
CGFloat height = 0.0f;
for (id key in _everyColumnHDict) {
CGFloat temHeight = [_everyColumnHDict[key] floatValue];
height = height > temHeight ? height : temHeight;
}
//遍歷字典,找出最高的那一列,返回高度
return CGSizeMake(self.collectionView.frame.size.width, height + _sectionInset.bottom);
11.重寫layoutAttributesForElementsInRect方法
return _attributeArr;
註釋寫的非常清楚了,列數、邊距之類的自己改下第4步的引數即可。有不明白的也可以看Demo,歡迎大家Star.
[1]:需要注意第三句程式碼,UITableView可以自己建立新的cell,不一定非要註冊,但CollectionView必須要註冊才可使用。 ↩
[2]:_everyColumnHDict字典的key值代表第幾列,value值代表這一列的高度,這裡只是設定了初始值,無論第幾列,第一行的高度都是_sectionInset.top;_attributeArr陣列中儲存的是每一個item的佈局約束 ↩
文/CrazySteven(簡書作者)
原文連結:http://www.jianshu.com/p/750ff6aa424d
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。