The implementation of the simple waterfall stream of iOS

Source: Internet
Author: User

The implementation of the simple waterfall stream of iOS 

Objective

Ultra-simple waterfall flow implementation, here to say the author's ideas, detailed code here.

Implementation ideas

CollectionView can realize the layout of each mid-boom, its essence lies in the uicollectionviewlayout, so we want to customize a layout to inherit the system Uicollectionviewlayout, All work is done in this class.

1. Define the required properties

The idea of a waterfall flow is that from top to bottom, that column is the shortest, the next item is placed in which column, so we need to define a dictionary to record the maximum Y value for each column

Each item has a attributes, so define an array to hold each item's attributes.

We also have to know how many columns and column spacing, line spacing, section to CollectionView margins.

//总列数 @property (nonatomic, assign) NSInteger columnCount; //列间距 @property (nonatomic, assign) NSInteger columnSpacing; //行间距 @property (nonatomic, assign) NSInteger rowSpacing; //section到collectionView的边距 @property (nonatomic, assign) UIEdgeInsets sectionInset; //保存每一列最大y值的数组 @property (nonatomic, strong) NSMutableDictionary *maxYDic; //保存每一个item的attributes的数组 @property (nonatomic, strong) NSMutableArray *attributesArray;

2. Overriding System methods

We need to rewrite 4 methods altogether.

1)- (void)prepareLayout 2)- (CGSize)collectionViewContentSize 3)- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 4)- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

-(void) Preparelayout method

Some of the pre-layout work is done here, initializing the dictionary, there are several key-value pairs in several columns, key is the first column, value is the maximum y value of the column, and the initial value is the top padding:

for  (int i = 0; i < self.columnCount; i++) {      self.maxYDic[@(i)] = @(self.sectionInset.top); }

Create the attributes for each item and deposit the array:

//根据collectionView获取总共有多少个item NSInteger itemCount = [self.collectionView numberOfItemsInSection:0]; //为每一个item创建一个attributes并存入数组 for  (int i = 0; i < itemCount; i++) {      UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];      [self.attributesArray addObject:attributes]; }

-(Cgsize) Collectionviewcontentsize method

The contentsize used to calculate CollectionView.

General waterfall flow can only scroll vertically, cannot scroll horizontally, so contentsize.width = 0, we only need to calculate the contentsize.height can

Find the maximum Y value of the longest column from the dictionary, plus the padding below, which is contentsize.height

- (CGSize)collectionViewContentSize {      //假设第0列是最长的那列      __block NSNumber *maxIndex = @0;      //遍历字典,找出最长的那一列      [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {          //如果maxColumn列的最大y值小于obj,则让maxColumn等于obj所属的列          if ([self.maxYDic[maxIndex] floatValue] < obj.floatValue) {              maxIndex = key;          }      }];      //collectionView的contentSize.height就等于最长列的最大y值+下内边距      return CGSizeMake(0, [self.maxYDic[maxIndex] floatValue] + self.sectionInset.bottom); }

-(Uicollectionviewlayoutattributes *) Layoutattributesforitematindexpath: (Nsindexpath *) IndexPath method

This method is used to set the attributes of each item, where we simply set the attributes.frame of each item

First we have to know the size of the CollectionView, and then we calculate the width of each item according to the width of the CollectionView, as well as the number of columns, each spacing.

Item width = (width of CollectionView-padding and column padding)/Number of columns

CGFloat collectionViewWidth = self.collectionView.frame.size.width;//self.sectionInset.left:左边距    self.sectionInset.right:右边距//(self.columnCount - 1) * columnSpacing:一行中所有的列边距CGFloat itemWidth = (collectionViewWidth - self.sectionInset.left - self.sectionInset.right - (self.columnCount - 1) * self.columnSpacing) / self.columnCount;

Next, to calculate the coordinates of the item, to calculate the coordinates, you must know the shortest column, walk through the dictionary, and find out which column (Mincolumn) the shortest column is and its maximum y value.

The Y value of item equals the maximum Y value of the shortest column plus the line spacing, and the X value equals the left margin + (item width + column spacing) * mincolumn

//找出最短的那一列 __block NSNumber *minIndex = @0; [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {      if  ([self.maxYDic[minIndex] floatValue] > obj.floatValue) {          minIndex = key;      } }]; //根据最短列的列数计算item的x值 CGFloat itemX = self.sectionInset.left + (self.columnSpacing + itemWidth) * minIndex.integerValue; //item的y值 = 最短列的最大y值 + 行间距 CGFloat itemY = [self.maxYDic[minIndex] floatValue] + self.rowSpacing;

Next is the height of the item, we should calculate the height according to the original size of the image and the calculated width, and so on, but in the layout class, we can't get the picture, so we can define a block property, or proxy, let the outside to calculate and return to us, We need to pass the width of the item and the Indexpath to the outside world:

@property (nonatomic, Strong) CGFloat (^itemheightblock) (CGFloat itemheight,nsindexpath *indexpath);

Sets the height of item according to the return value:

if(self.itemHeightBlock) itemHeight = self.itemHeightBlock(itemWidth, indexPath);

Finally, set the attributes frame and update the dictionary:

//设置attributes的frame attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight); //更新字典中的最短列的最大y值 self.maxYDic[minIndex] = @(CGRectGetMaxY(attributes.frame));

-(Nsarray *) Layoutattributesforelementsinrect: (cgrect) Rect method

The method is used to return the attributes of the item within the RECT range.

return directly to Attributesarray

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return  self.attributesArray; }

Use

The layout class is finished, and then you can use it directly.

//Create layout object xrwaterfalllayout *waterfall = [[xrwaterfalllayout  Alloc] init]; //Setting related properties waterfall.columncount = 3; //Total number of columns waterfall.columnspacing = 10; //Column spacing waterfall.rowspacing = 10; //Line spacing Waterfall.sectioninset = uiedgeinsetsmake (10, 10 , 10, 10); //Padding [Waterfall setitemheightblock:^cgfloat (Cgfloat itemwidth, nsindexpath *indexpath)  { //Calculate the display height according to the original size of the picture, and the display width, and so on, xrimage *image = self.images[ Indexpath.item]; return   image.imageh / image.imagew * itemwidth; }]; Collectionview.collectionviewlayout = waterfall; ... ...

Specific code please download here: https://github.com/codingZero/XRWaterfallLayout, feel good, please offer your star

The implementation of the simple waterfall stream of iOS

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.