不规则瀑布流

封装的layout

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol WaterLayoutDelegate <NSObject>

@required
- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath;




@end
@interface WJY_WaterFallLayout : UICollectionViewLayout
@property (nonatomic, assign) id<WaterLayoutDelegate> delegate;
// 行数
@property (nonatomic, assign) NSInteger lineCount;
// 水平间距
@property (nonatomic, assign) CGFloat verticalSpacing;
// 垂直间距
@property (nonatomic, assign) CGFloat horizontalSpacing;
@property (nonatomic, assign) UIEdgeInsets sectionInset;
@end

#import "WJY_WaterFallLayout.h"

@interface WJY_WaterFallLayout()
@property (nonatomic, retain) NSMutableArray *heights;
@property (nonatomic, retain) NSMutableArray *originX;
@property (nonatomic, retain) NSMutableDictionary *itemsArrange;

@property (nonatomic, retain) NSMutableDictionary *itemsInitialArrange;

@end
@implementation WJY_WaterFallLayout
#pragma mark - 重写,应 始终调用子类
- (void)prepareLayout
{
    // 如果item 是0 返回
    NSInteger cellCount = [self.collectionView numberOfItemsInSection:0];
    if (cellCount == 0) {
        return ;
    }
    // 调转系统的协议方法 并设置代理
    self.delegate = (id<WaterLayoutDelegate>)self.collectionView.delegate;
    
    self.itemsArrange = [NSMutableDictionary dictionary];
    self.itemsInitialArrange = [NSMutableDictionary dictionary];
    
    [self initAllarrays];

    for (NSInteger i = 0; i < cellCount; i++) {
        [
         self layoutForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
    }

}
#pragma 初始化所以数组
- (void)initAllarrays
{
    
    self.heights = [NSMutableArray array];
    self.originX = [NSMutableArray array];
    // item宽度
    CGFloat itemWidth   = ([UIScreen mainScreen].bounds.size.width - self.sectionInset.left - self.sectionInset.right - (self.lineCount - 1) * self.horizontalSpacing) / self.lineCount;
    
    for (NSInteger i = 0; i < self.lineCount; i++) {
        
        // 循环添加 每行的每个top的点到 height数组中
        [self.heights addObject:[NSNumber numberWithDouble:self.sectionInset.top]];
        
        //设置oringin_x 为0
        CGFloat oringin_x   = 0.0;
        
        if (i == 0) {
         //i = 0 x点 = left;
            oringin_x = self.sectionInset.left;
        } else {
            //  x = i + item宽 + 横向宽度
            oringin_x = [self.originX[i - 1] doubleValue] + itemWidth + self.horizontalSpacing;
        }
         // 把得到的点加到 x数组中
        [self.originX addObject:[NSNumber numberWithDouble: oringin_x]];
    }

}
#pragma mark - itme设置
- (void)layoutForItemAtIndexPath:(NSIndexPath *)indexPath
{
    
    CGRect rect = CGRectZero;
    // 协议方法
    CGSize size = [self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
    
    rect.size.height = size.height;
    
    rect.size.width  = ([UIScreen mainScreen].bounds.size.width  - self.sectionInset.left - self.sectionInset.right - (self.lineCount - 1) * self.horizontalSpacing) / self.lineCount;
    
    NSInteger index  = [self getLowerHeightRowIndex:self.heights];
    
    rect.origin.x = [self.originX[index] doubleValue];
    rect.origin.y = [self.heights[index] doubleValue];
    
    CGFloat newHeight = rect.origin.y + rect.size.height + self.verticalSpacing;
    
    [self.heights replaceObjectAtIndex:index withObject:[NSNumber numberWithDouble: newHeight]];
    
    [self.itemsArrange setObject:indexPath forKey:NSStringFromCGRect(rect)];
    
    [self.itemsInitialArrange setObject:indexPath forKey:NSStringFromCGRect(CGRectMake(rect.origin.x, rect.origin.y - [UIScreen mainScreen].bounds.size.height, rect.size.width, rect.size.height))];
}
#pragma mark - 子类必须重写此方法并使用它来返回的宽度和高度的视图的内容。这些值表示的宽度和高度的所有内容,视图使用此信息来配置其自身内容的大小,以便滚动。
- (CGSize)collectionViewContentSize
{
    
    
    CGFloat heightest = [self getHeightest:self.heights];
    
    CGSize size = CGSizeMake(0, heightest);
    
    return size;
}
#pragma mark - 设置布局信息
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    NSArray *keyArr = self.itemsArrange.allKeys;
    
    for (NSString *rectStr in keyArr) {

        if (self.itemsArrange[rectStr] != indexPath) {
            continue;
        }
        
        CGRect rect = CGRectFromString(rectStr);
        
        attributes.frame = rect;
        
        break;
        
    }
    
    return attributes;
}
#pragma mark - 重新自定义layout
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
    // layout初始化方法
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:itemIndexPath];
    
    NSArray *keyArr = self.itemsArrange.allKeys;
    
    for (NSString *rectStr in keyArr) {
        // item的rect信息和布局信息不等 就跳出本次循环
        if (self.itemsInitialArrange[rectStr] != itemIndexPath) {
            continue;
        }
        
        CGRect rect = CGRectFromString(rectStr);
        
        attributes.frame = rect;
        
        break;
        
    }
    
    return attributes;
}

#pragma mark - 布局属性返回数组 视图在给定矩形
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    
    CGFloat up = rect.origin.y;
    
    CGFloat down = rect.origin.y + rect.size.height;
    
    NSMutableArray *attributes = [NSMutableArray array];
    
    for (NSString *rectStr in self.itemsArrange) {
        
        CGRect itemRect = CGRectFromString(rectStr);
        
        if (itemRect.origin.y <= down && itemRect.origin.y + itemRect.size.height >= up) {
            
            NSIndexPath *indexPath = [self.itemsArrange objectForKey:rectStr];
            
                    //设置布局信息 添加到数组里
            [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
        }
    }
    
    return attributes;
}
# pragma mark - 获取低行高
- (NSInteger)getLowerHeightRowIndex:(NSMutableArray *)height {
    
    if (height.count == 0) {
        return 0;
    }
    
    NSInteger index  = 0;
    
    CGFloat heightest = [height[0] doubleValue];
    
    for (NSInteger i  = 1; i < height.count; i++) {
        // 判定获取低行位置
        index = heightest > [height[i] doubleValue] ? i : index;
    }
    
    return index;
}
# pragma mark - 获取高度
- (CGFloat)getHeightest:(NSMutableArray *)height {
    
    if (height.count == 0) {
        return 0;
    }
    
    CGFloat heightest = self.sectionInset.top;
    // 遍历最高点
    for (NSInteger i  = 0; i < height.count; i++) {
        // 如果heightest为最高点返回返回 如果不是则返回height
        heightest  = heightest > [height[i] doubleValue] ? heightest : [height[i] doubleValue];
    }
    
    return heightest;
}


@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值