iOS瀑布流Demo

// 代码参考小码哥

//

//  Ago_flowLatout.h

//  瀑布流-text

//

//  Created by  mac on 16/5/23.

//  Copyright © 2016 hkzr. All rights reserved.

//


#import <UIKit/UIKit.h>

@class Ago_flowLatout;

@protocol Ago_flowLatoutDelegate <NSObject>

@required

//设置代理设置图片的高度

- (CGFloat)waterflowLayout:(Ago_flowLatout *)waterflowLayout heightForItemAtIndex:(NSUInteger)index itemWidth:(CGFloat)itemWidth;


@optional

//列数

- (CGFloat)columnCountInWaterflowLayout:(Ago_flowLatout *)waterflowLayout;

//列间距

- (CGFloat)columnMarginInWaterflowLayout:(Ago_flowLatout *)waterflowLayout;

//行间距

- (CGFloat)rowMarginInWaterflowLayout:(Ago_flowLatout *)waterflowLayout;

//edge设置

- (UIEdgeInsets)edgeInsetsInWaterflowLayout:(Ago_flowLatout *)waterflowLayout;

@end

@interface Ago_flowLatout : UICollectionViewLayout

@property (nonatomic,weak)id <Ago_flowLatoutDelegate> delegate;

@end




//

//  Ago_flowLatout.m

//  瀑布流-text

//

//  Created by  mac on 16/5/23.

//  Copyright © 2016 hkzr. All rights reserved.

//


#import "Ago_flowLatout.h"

/**默认的列数*/

static const NSInteger DefaultColumnCount = 3;

/** 每一列之间的间距 */

static const CGFloat DefaultColumnMargin = 10;

/** 每一行之间的间距 */

static const CGFloat DefaultRowMargin = 10;

/** 边缘间距 */

static const UIEdgeInsets DefaultEdgeInsets = {10, 10, 10, 10};


@interface Ago_flowLatout()

/** 存放所有cell的布局属性 */

@property (nonatomic, strong) NSMutableArray *attrsArray;

/** 存放所有列的当前高度 */

@property (nonatomic, strong) NSMutableArray *columnHeights;


- (CGFloat)rowMargin;

- (CGFloat)columnMargin;

- (NSInteger)columnCount;

- (UIEdgeInsets)edgeInsets;

@end


@implementation Ago_flowLatout

#pragma 手动设置各种间距

- (CGFloat)rowMargin

{

    if ([self.delegate respondsToSelector:@selector(rowMarginInWaterflowLayout:)]) {

        return [self.delegate rowMarginInWaterflowLayout:self];

    } else {

        return DefaultRowMargin;

    }

}

- (CGFloat)columnMargin

{

    if ([self.delegate respondsToSelector:@selector(columnMarginInWaterflowLayout:)]) {

        return [self.delegate columnMarginInWaterflowLayout:self];

    } else {

        return DefaultColumnMargin;

    }

}

- (NSInteger)columnCount

{

    if ([self.delegate respondsToSelector:@selector(columnCountInWaterflowLayout:)]) {

        return [self.delegate columnCountInWaterflowLayout:self];

    } else {

        return DefaultColumnCount;

    }

}

- (UIEdgeInsets)edgeInsets

{

    if ([self.delegate respondsToSelector:@selector(edgeInsetsInWaterflowLayout:)]) {

        return [self.delegate edgeInsetsInWaterflowLayout:self];

    } else {

        return DefaultEdgeInsets;

    }

}

#pragma mark 懒加载

- (NSMutableArray *)columnHeights

{

    if (!_columnHeights) {

        _columnHeights = [NSMutableArray array];

    }

    return _columnHeights;

}


- (NSMutableArray *)attrsArray

{

    if (!_attrsArray) {

        _attrsArray = [NSMutableArray array];

    }

    return _attrsArray;

}

/**

 * 初始化

 */

- (void)prepareLayout{

   [super prepareLayout];

    // 清除以前计算的所有高度

    [self.columnHeights removeAllObjects];

    //获取顶部Edge

    for (NSInteger i = 0; i < DefaultColumnCount; i++) {

        [self.columnHeights addObject:@(self.edgeInsets.top)];

    }

    // 清除之前所有的布局属性

    [self.attrsArray removeAllObjects];

     // 开始创建每一个cell对应的布局属性

    NSInteger count = [self.collectionView numberOfItemsInSection:0];

    for (NSInteger i = 0; i < count; i++){

        // 创建位置

        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];

        // 获取indexPath位置cell对应的布局属性

        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];

        [self.attrsArray addObject:attrs];

    

    }


}

/**

 * 决定cell的排布

 */

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

{

    return self.attrsArray;

}

/**

 * 返回indexPath位置cell对应的布局属性

 */

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{

    // 创建布局属性

    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    // collectionView的宽度

    CGFloat collectionViewW = self.collectionView.frame.size.width;

    CGFloat w = (collectionViewW -self.edgeInsets.left -self.edgeInsets.right -(self.columnCount-1)*self.columnMargin )/self.columnCount;

//     CGFloat h = 50 + arc4random_uniform(100);

    CGFloat h = [self.delegate waterflowLayout:self heightForItemAtIndex:indexPath.item itemWidth:w];

    // 找出高度最短的那一列

    NSInteger destColumn = 0;

    //假如最小一行为第一行

    CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];

    //比较出最短的一行

    for (NSInteger i = 1; i < self.columnCount; i++){

        // 取得第i列的高度

        CGFloat columnHeight = [self.columnHeights[i] doubleValue];

        //假如最短的一列高度 大于第i个的高度

        if (minColumnHeight > columnHeight) {

            //最短的更新

            minColumnHeight = columnHeight;

            //i即为最短

            destColumn = i;

        }

    }

    //找到最短的一行之后,取出下个cell要放的位置

    CGFloat x = self.edgeInsets.left + destColumn * (w + self.columnMargin);

    CGFloat y = minColumnHeight;

     if (y != self.edgeInsets.top)y += self.rowMargin;

    attrs.frame = CGRectMake(x, y, w, h);

    // 更新最短那列的高度

    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));

    

    return attrs;

}

- (CGSize)collectionViewContentSize{

    CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue];

    for (NSInteger i = 1; i < self.columnCount; i++) {

        // 取得第i列的高度

        CGFloat columnHeight = [self.columnHeights[i] doubleValue];

        

        if (maxColumnHeight < columnHeight) {

            maxColumnHeight = columnHeight;

        }

    }

    return CGSizeMake(0, maxColumnHeight +self.edgeInsets.bottom);


}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使 iOS 瀑布流的 cell 完全展示在屏幕中,您需要做到以下几点: 1. 设置 UICollectionView 的 contentInset 属性,以便 cell 与屏幕边缘之间有足够的间距。 2. 在 UICollectionViewDelegateFlowLayout 协议的方法中,设置每个 section 的 inset。 3. 在 UICollectionViewDelegateFlowLayout 协议的方法中,确定每个 cell 的大小。 4. 在 UICollectionViewDelegate 协议的方法中,使用 indexPathsForVisibleItems 属性获取当前可见的 cell。 5. 对于每个可见的 cell,使用 rectForItem(at:) 方法获取其在 UICollectionView 中的 frame。 6. 使用 CGRectContainsRect() 方法检查 cell 的 frame 是否完全包含在屏幕中。如果是,则 cell 完全展示在屏幕中;如果不是,则需要调整 UICollectionView 的 contentOffset 属性以确保 cell 完全展示在屏幕中。 以下是代码示例: ```swift func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { let visibleCells = collectionView.indexPathsForVisibleItems for visibleIndexPath in visibleCells { if let visibleCell = collectionView.cellForItem(at: visibleIndexPath) { let cellFrame = collectionView.convert(visibleCell.frame, to: collectionView.superview) let screenFrame = UIScreen.main.bounds if !CGRectContainsRect(screenFrame, cellFrame) { let offsetY = max(0, cellFrame.maxY - screenFrame.maxY) collectionView.setContentOffset(CGPoint(x: 0, y: collectionView.contentOffset.y + offsetY), animated: true) } } } } ``` 注意,这只是一个示例代码,具体实现可能因您的需求而异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值