使用CollectionView实现,因为CollectionView相对于Tableview来说,可以自定义布局方式.
1.实现数据源
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 100;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
cell.backgroundColor
= [UIColor colorWithRed:arc4random_uniform(255) / 255.0 green:arc4random_uniform(255) / 255.0 blue:arc4random_uniform(255) / 255.0 alpha:1];
return cell;
}
2.�继承UICollectionViewDelegateFlowLayout协议,实现代理 (sizeForItemAtIndexPath),告诉系统每个item的Size
//�如果使用了自定义布局,�这个方法就可以去掉了
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
CGFloat height = 100 + (arc4random() % 150);//随机一个高度
CGSize size = CGSizeMake(100, height);
return size;
}
//��下面�使用瀑布流,使用到的高度在这里随机出来,通过代理传给ViewLayout子类
/*
- (CGFloat) collectionView:(UICollectionView*) collectionView
layout:(MKMasonryViewLayout*) layout
heightForItemAtIndexPath:(NSIndexPath*) indexPath {
CGFloat randomHeight = 100 + (arc4random() % 140);
return randomHeight;
}
*/
写到这里,cmd+R运行,回到杂乱无章的布局,不是想要的效果
3.这个时候需要自定义布局,创建UICollectionViewLayout子类,重写方法
3.1 prepareLayout 集合视图开始布局之前会被调用
3.2 layoutAttributesForElementsInRect:
3.3 collectionViewContentSize 计算出整个集合视图的大小
ViewLayout子类的主要职责是:
1.�计算每个item的边框
2.计算出集合视图的内容大小.
我们的目的:
1.计算出边框,缓存在某处
2.通过某代理将每个item的尺寸传给系统
3.拿到最后一个item的maxY作为集合视图的高度
声明变量
NSUInteger numberOfColumns--确定列数
CGFloat interItemSpacing--确定间隔
CGFloat lastYValueForColumn--瀑布流特点:上个item的maxY+interItemSpacing,作为下个item的Y坐标
NSMutableDictionary *lastYValueForColumn--�缓存高度
NSMutableDictionary *layoutInfo--��缓存ViewLayoutAttributes�属性(�里面保存着每个item的frame)
//1.在prepareLayout计算出每个item的坐标和尺寸,缓存起来;
-(void) prepareLayout {
self.numberOfColumns = 3;
self.interItemSpacing = 12.5;
self.lastYValueForColumn = [NSMutableDictionary dictionary];
CGFloat currentColumn = 0;
CGFloat fullWidth = self.collectionView.frame.size.width;
CGFloat availableSpaceExcludingPadding = fullWidth - (self.interItemSpacing * (self.numberOfColumns + 1));
CGFloat itemWidth = availableSpaceExcludingPadding / self.numberOfColumns; //算出itemWidth
self.layoutInfo = [NSMutableDictionary dictionary];
NSIndexPath *indexPath;
NSInteger numSections = [self.collectionView numberOfSections];
for(NSInteger section = 0; section < numSections; section++) {
NSInteger numItems = [self.collectionView numberOfItemsInSection:section];
for(NSInteger item = 0; item < numItems; item++){
indexPath = [NSIndexPath indexPathForItem:item inSection:section];
UICollectionViewLayoutAttributes *itemAttributes =
[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGFloat x ;
CGFloat y;
if (item > 2) {
//找出最短的item所在的Column
NSInteger count = self.lastYValueForColumn.allValues.count;
NSNumber * tempY = self.lastYValueForColumn.allValues[0];
NSNumber * shortestColumn ;
for (int i = 0; i < count; i++) {
NSNumber * Y = self.lastYValueForColumn.allValues[i];
if ([Y floatValue] < [tempY floatValue]) {
tempY = Y;
shortestColumn = self.lastYValueForColumn.allKeys[i];
}
}
x = self.interItemSpacing + (self.interItemSpacing + itemWidth) * [shortestColumn integerValue];
NSLog(@"%@",self.lastYValueForColumn);
NSLog(@"X : %f 最短的Column: %zd ",x, [shortestColumn integerValue]);
y = [self.lastYValueForColumn[@( [shortestColumn integerValue])] doubleValue];
//高度是在collectionView所在的控制器拿到的,通过代理将高度传过来
CGFloat height = [((id)self.collectionView.delegate)
collectionView:self.collectionView
layout:self
heightForItemAtIndexPath:indexPath];
itemAttributes.frame = CGRectMake(x, y, itemWidth, height);
y+= height;
y += self.interItemSpacing;
self.lastYValueForColumn[@([shortestColumn integerValue])] = @(y);
}
else{
x = self.interItemSpacing + (self.interItemSpacing + itemWidth) * currentColumn;
NSLog(@"X : %f currentColumn: %f",x,currentColumn);
y = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
CGFloat height = [((id)self.collectionView.delegate)
collectionView:self.collectionView
layout:self
heightForItemAtIndexPath:indexPath];
itemAttributes.frame = CGRectMake(x, y, itemWidth, height);
y+= height;
y += self.interItemSpacing;
self.lastYValueForColumn[@(currentColumn)] = @(y);
currentColumn ++;
if(currentColumn == self.numberOfColumns) {
currentColumn = 0;
NSLog(@"-----------------------------");
}
}
self.layoutInfo[indexPath] = itemAttributes;
}
}
}
//2.通过该代理将尺寸传给系统
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.layoutInfo.count];
[self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
UICollectionViewLayoutAttributes *attributes,
BOOL *stop) {
if (CGRectIntersectsRect(rect, attributes.frame)) { //找出与可见区域rect相交的item数组,
[allAttributes addObject:attributes];
}
}];
return allAttributes;
}
//3.找到最高的那一个item的高度,最为集合视图的高度
-(CGSize) collectionViewContentSize {
NSUInteger currentColumn = 0;
CGFloat maxHeight = 0;
do {
CGFloat height = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
if(height > maxHeight)
maxHeight = height;
currentColumn ++;
} while (currentColumn < self.numberOfColumns);
return CGSizeMake(self.collectionView.frame.size.width, maxHeight);
}
---Refer to iOS 7 Programming Pushing the Limits.