关于瀑布流的实现网上有很多种解法,自定义控件,TableView+ScrollView,UICollectionView是iOS6发布之后用于展示集合视图,算起来已经发布三年左右了,不过知识点是不变的,集合视图提供了一个更优雅的方式去展示图片或者文字信息。UICollectionView与UITableView相似,UICollectionViewController与UITableViewController都负责视图,存储需要的数据,并且能处理数据源与委托协议。
简单瀑布流
首先来看一个简单的UICollectionView实现瀑布流的过程,熟悉之后就可以实现稍微实用的瀑布流:
1.故事板中拖拽一个UICollectionView放在视图中,效果如下:
2.新建一个继承子UICollectionViewCell的子类MyCollectionViewCell,将单元格的Class选定为MyCollectionViewCell,并且设置Identifier为MyCell。
3.实现UICollectionViewDelegate,UICollectionViewDataSource,设置区域,设置区域中的Item个数,生成可复用的单元格:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ return 1; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return 100; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ MyCollectionViewCell *myCell=[collectionView dequeueReusableCellWithReuseIdentifier: @"MyCell" forIndexPath:indexPath]; [myCell setBackgroundColor:[UIColor greenColor]]; return myCell; }
viewDidLoad中设置一下数据源和代理:
self.collectionView.delegate=self; self.collectionView.dataSource=self; self.collectionView.backgroundColor=[UIColor whiteColor];
最终效果如下:
石工布局(瀑布流)
上面那种效果其实还是比较简单的,很多情况下所有的单元格的宽度是一定的,只是高度不确定,这就是有些人说的定宽不定高,主要是从视觉上的美感来看,当然我们可以通过实现UICollectionViewDelegateFlowLayout去改变单元格大小:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ CGFloat height=100+(arc4ranDOM()%100); return CGSizeMake(100, height); }
通过效果我们可以发现,同一行的单元格的圆心所在的Y轴坐标都是一样的:
石工布局(masonry layout)最早是Pinterest使用,石工简单理解就是前面贴砖的时候每块砖肯能是长方形的也可能正方形的,最终贴出来的效果是长方形或者正方形,国内的话基本上就称为瀑布流,早先是Web网站上流行,现在在手机上看,有些Web甚至整个网站的内容都在一个瀑布流页面,也有点审美疲劳的感觉。
这次先看下最终实现的效果:
这个应该算是最常见的布局模式了,这个的实现很简单,为了Demo的效果没有没有采取任何优化措施,仅供入门参考,设置存储所有高度的数组:
//存储所有的高度的数组 @property (strong,nonatomic) NSMutableArray *heightArr;
将高度添加到数组中:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ CGFloat height=100+(arc4random()%160); [self.heightArr addObject:[NSString stringWithFormat:@"%f",height]]; return CGSizeMake(100, height); }
修改每一行单元格的位置:
// [myCell setBackgroundColor:[UIColor greenColor]]; // return myCell; //} -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ MyCollectionViewCell *myCell=[collectionView dequeueReusableCellWithReuseIdentifier: @"MyCell" forIndexPath:indexPath]; [myCell setBackgroundColor:[UIColor redColor]]; NSInteger remainder=indexPath.row%3; NSInteger currentRow=indexPath.row/3; CGFloat currentHeight=[self.heightArr[indexPath.row] floatValue]; CGFloat positonX=100*remainder+10*(remainder+1); CGFloat positionY=(currentRow+1)*10; for (NSInteger i=0; i<currentRow; i++) { NSInteger position=remainder+i*3; positionY+=[self.heightArr[position] floatValue]; } myCell.frame = CGRectMake(positonX, positionY,100,currentHeight) ; NSUInteger *randomNumber=arc4random_uniform(9); NSString *girlFilename = [NSString stringWithFormat:@"Girl%lu.jpg", (unsigned long)randomNumber]; UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:girlFilename]]; [myCell setBackgroundView:imageView]; return myCell; }
效果演示: