自訂UICollectinviewFlowLayout,即實現瀑布流,ios自訂flowlayout

來源:互聯網
上載者:User

自訂UICollectinviewFlowLayout,即實現瀑布流,ios自訂flowlayout

,通過實現不規則的網格分布,來顯示出不同的效果。因為集合視圖必須要指定布局還可以顯示,所以自訂布局就可以實現瀑布流的效果。

//建立布局對象    WaterFlowLayout *flowLayout = [[WaterFlowLayout alloc] init];        flowLayout.delegate = self;    flowLayout.numberOfColumn = 3;        //建立集合視圖    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:flowLayout];

因為系統內建的布局有四個方法,分別實現了item大小,分區間隔,最小行間距,item之間的間隙大小

@protocol UICollectionViewDelegateFlowLayout <UICollectionViewDelegate>@optional- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;

所以,自訂FlowLayout,並定義協議,以便定義這些方法。

@protocol WaterFlowLayoutDelegate <NSObject>//關鍵方法,此方法的作用是返回每一個item的size大小//資料中原始圖片大小- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;//分區間隔- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;//得到 item之間的間隙大小- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;//最小行間距- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;@end@interface WaterFlowLayout : UICollectionViewLayout//瀑布流一共多少列@property (nonatomic, assign) NSUInteger numberOfColumn;@property (nonatomic, assign) id<WaterFlowLayoutDelegate>delegate;

看圖可知,最小高的的item,將作為下一列item的起點。

@interface WaterFlowLayout ()//存放每一列的高度@property (nonatomic, retain) NSMutableArray *columnHeightsArray;//存放 每一個item的 屬性 包含 frame以及下標@property (nonatomic, retain) NSMutableArray *attributesArray;@end@implementation WaterFlowLayout//擷取最小高度的方法- (CGFloat)minHeight{    CGFloat min = 100000;    for (NSNumber *height in _columnHeightsArray) {        CGFloat h = [height floatValue];        if (min > h) {            min = h;        }    }    return min;}//擷取最大值- (CGFloat)maxHeight{    CGFloat max = 0;    for (NSNumber *height in _columnHeightsArray) {        CGFloat h = [height floatValue];        if (max < h) {            max = h;        }    }    return max;}//找到最小高的下標- (NSUInteger)indexOfMinHeight{    NSUInteger index = 0;    for (int i = 0; i < [_columnHeightsArray count]; i ++) {        CGFloat height = [_columnHeightsArray[i] floatValue];        if (height == [self minHeight]) {            index = i;            return index;        }    }    return index;}//重寫父類的布局方法- (void)prepareLayout{    [super prepareLayout];        _attributesArray = [[NSMutableArray alloc] init];        _columnHeightsArray = [[NSMutableArray alloc] initWithCapacity:self.numberOfColumn];        //給列高數組裡面的對象賦初值    for (int i = 0; i < self.numberOfColumn; i ++) {        [_columnHeightsArray addObject:@0.0];    }        CGFloat totalWidth = self.collectionView.frame.size.width;        //建立 每個item frame中的x、y    CGFloat x = 0;    CGFloat y = 0;        NSUInteger itemCount = [self.collectionView numberOfItemsInSection:0];        for (int i = 0; i < itemCount; i ++) {        //得到集合視圖中 列間隙的個數        NSUInteger numberOfSpace = self.numberOfColumn - 1;                //代理對象執行代理方法,得到 item之間的間隙大小        CGFloat spaceWidth = [_delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:0];                //求每列的寬度,也就是每個item的width        CGFloat width = (totalWidth - spaceWidth * numberOfSpace) / self.numberOfColumn;                        //擷取每一個itemSize的大小        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];                //資料中原始圖片大小        CGSize imageSize = [_delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];            //通過 約分公式得到固定寬之後的高度是多少        CGFloat height = width * imageSize.height / imageSize.width;                        UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];                //記錄每一個item的大小和位置        attribute.frame = CGRectMake(x, y, width, height);                //數組儲存每個item的位置資訊        [_attributesArray addObject:attribute];                NSLog(@"item = %d",i);        NSLog(@"x = %.2f y = %.2f width = %.2f height = %.2f",x,y,width,height);                //求列高最小的那一列的下標        NSUInteger minHeightIndex = [self indexOfMinHeight];                //求出最小列的高度        CGFloat minHeight = [_columnHeightsArray[minHeightIndex] floatValue];                //求出行高        CGFloat lineHeight = [_delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:0];                //上一次總的列高 加上 行高 加上新加上的item的height,才是現在這一列的總高度        //minHeight為最小列現在的高度        //lineHeight為行間距        //height為新加的item的高        _columnHeightsArray[minHeightIndex] = [NSNumber numberWithFloat:minHeight + lineHeight + height];                //重新算最小列高的下標        minHeightIndex = [self indexOfMinHeight];                //算下一次新加的item的x和y值        x = (spaceWidth + width) * minHeightIndex;                y = [self minHeight];    }}//重寫這個方法,可以返回集合視圖的總高度- (CGSize)collectionViewContentSize{    return CGSizeMake(self.collectionView.frame.size.width, [self maxHeight]);}- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{    return _attributesArray;}

注意,最後一個方法的實現,即- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect,如果這個方法不寫,集合視圖是顯示不出來的,這個方法是次儲存的每個item的資訊重新告訴集合視圖,進行顯示。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.