iOS UICollectionView 瀑布流

在学习开源项目:豆瓣相册-精选集https://github.com/cbknight/CBDoubanAlbum,使用到瀑布流展示图片,因此学习下iOS瀑布流。

1. UIScrollView 与 UICollectionView

UISCrollView:

优点:

1.灵活调节子控件,可边展示,边编辑图片(casatwy架构的App:Play+)。

缺点:

1.需要自己缓存子控件(未显示在scrollview上);

2.需要监听scrollview滚动,不显的控件从父控件上移除,添加到缓存set集合中,以便于复用;

3.需要布局每个子控件。

UIScollectionView:

优点:

1.UIScollectionView系统已做好了缓存机制,可以复用,简单易用。

缺点:

2.仅显示。

2. UICollectionView实现:UICollectionViewDataSource和UICollectionViewDelegateFlowLayout

1. 自定义流水布局中,指定滚动方向、默认列数、行间距、列间距、以及指定cell的大小itemSize:

1 #pragma mark - UICollectionViewDataSource
2 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
3 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
4 
5 #pragma mark - UICollectionViewDelegateFlowLayout
6 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
7 - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;

3. 继承UICollectionViewCell:

1. 简单Demo,就展示ImageView:

1 @property (nonatomic, strong) UIImageView *imageView;

2. 使用AutoLayout布局imageView:

 1 - (instancetype)initWithFrame:(CGRect)frame
 2 {
 3     self = [super initWithFrame:frame];
 4     if (self) {
 5         self.imageView = [[UIImageView alloc] init];
 6         self.imageView.translatesAutoresizingMaskIntoConstraints = NO;
 7         [self addSubview:self.imageView];
 8         
 9         NSArray *fillWidth = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_imageView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)];
10         NSArray *fillHeight = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_imageView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)];
11         [self addConstraints:fillWidth];
12         [self addConstraints:fillHeight];
13     }
14     return self;
15 }

4. 继承UICollectionViewFlowLayout

1. columnMaxYs数组(记录当前每一列的最大Y值),假如3列,我们就提供一个3个元素的数组,记录所有布局属性:

1 @property (nonatomic, assign) NSInteger column; // 列数
2 
3 @property (nonatomic, assign) id<UICollectionViewDelegateFlowLayout> delegate;
4 @property (nonatomic, strong) NSMutableArray *columnMaxYs; // 每一列的最大Y值
5 @property (nonatomic, strong) NSMutableDictionary *attributeDict; // 存放cell的布局属性
6 @property (nonatomic, assign) NSUInteger cellCount; // cell的个数

2. 在prepareLayout方法中 初始化:

至于为什么在prepareLayout方法中初始化,而不是在init方法初始化:

是因为,该方法每次刷新都会调用,而init方法中只会在创建布局对象的时候只执行一次,

例如:如果进行下拉刷新最新数据的时候,需求重新初始化数据,而如果我们使用的是init方法的话,并不会调用也就并不会清除之前的然后初始化, 而使用该方法prepareLayout可以办到,因为它会再次调用,而init不会调用。

1 - (void)prepareLayout;

3. 在layoutAttributesForItemAtIndexPath: 来调整 Cell的布局属性 ,指定Cell的 frame 。

1 - (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

1.在该方法中拿到当前cell的默认布局属性attrs,进行下面的调整,就可以实现瀑布流了

2.遍历columnMaxYs数组,需要找出最短一列的 列号 与 最大Y值

3.确定当前Cell的 存放的x.y位置 以及widht与height

   —> width:根据屏幕宽度与列数以及每列的宽度求出. height:服务器返回的

   —> x:需要根据当前最短一列的列号与Cell的宽度与间距可以求出来;y : 可以根据当前最短一列的最大Y值 + 行间距可以求出

4.重新设置修改当前Cell的布局属性attrs 的 frame即可。

  —> 之前已经拿到当前Cell的 默认布局属性,以及上一步已经获取到当前Cell需要存放的x.y位置后,

5.将修改Cell布局属性之后的,当前列当前Cell的Y值最大,所有我们要将该值记录到数组columnMaxYs中,以便下次对比

4. 在layoutAttributesForElementsInRect:方法(返回布局信息,如果忽略传入的rect一次性将所有的cell布局信息返回,图片过多时性能会很差

1 - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

5. 设置collectionView的contentSize,它才会滚动:

1 - (CGSize)collectionViewContentSize;

5.写的一个简单的瀑布流 Demo Github

6.一个开源瀑布流,可以使用Cocoapods:DDCollectionViewFlowLayout

原文地址:https://www.cnblogs.com/chrisbin/p/5473804.html