-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathXRWaterfallLayout.m
More file actions
138 lines (114 loc) · 4.72 KB
/
XRWaterfallLayout.m
File metadata and controls
138 lines (114 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//
// XRWaterfallLayout.m
//
// Created by 肖睿 on 16/3/29.
// Copyright © 2016年 XR. All rights reserved.
//
#import "XRWaterfallLayout.h"
@interface XRWaterfallLayout()
//用来记录每一列的最大y值
@property (nonatomic, strong) NSMutableDictionary *maxYDic;
//保存每一个item的attributes
@property (nonatomic, strong) NSMutableArray *attributesArray;
@end
@implementation XRWaterfallLayout
#pragma mark- 懒加载
- (NSMutableDictionary *)maxYDic {
if (!_maxYDic) {
_maxYDic = [[NSMutableDictionary alloc] init];
}
return _maxYDic;
}
- (NSMutableArray *)attributesArray {
if (!_attributesArray) {
_attributesArray = [NSMutableArray array];
}
return _attributesArray;
}
#pragma mark- 构造方法
- (instancetype)init {
if (self = [super init]) {
self.columnCount = 2;
}
return self;
}
- (instancetype)initWithColumnCount:(NSInteger)columnCount {
if (self = [super init]) {
self.columnCount = columnCount;
}
return self;
}
+ (instancetype)waterFallLayoutWithColumnCount:(NSInteger)columnCount {
return [[self alloc] initWithColumnCount:columnCount];
}
#pragma mark- 相关设置方法
- (void)setColumnSpacing:(NSInteger)columnSpacing rowSpacing:(NSInteger)rowSepacing sectionInset:(UIEdgeInsets)sectionInset {
self.columnSpacing = columnSpacing;
self.rowSpacing = rowSepacing;
self.sectionInset = sectionInset;
}
#pragma mark- 布局相关方法
//布局前的准备工作
- (void)prepareLayout {
[super prepareLayout];
//初始化字典,有几列就有几个键值对,key为列,value为列的最大y值,初始值为上内边距
for (int i = 0; i < self.columnCount; i++) {
self.maxYDic[@(i)] = @(self.sectionInset.top);
}
//根据collectionView获取总共有多少个item
NSInteger itemCount = [self.collectionView numberOfItemsInSection:0];
[self.attributesArray removeAllObjects];
//为每一个item创建一个attributes并存入数组
for (int i = 0; i < itemCount; i++) {
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
[self.attributesArray addObject:attributes];
}
}
//计算collectionView的contentSize
- (CGSize)collectionViewContentSize {
__block NSNumber *maxIndex = @0;
//遍历字典,找出最长的那一列
[self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {
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 {
//根据indexPath获取item的attributes
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//获取collectionView的宽度
CGFloat collectionViewWidth = self.collectionView.frame.size.width;
//item的宽度 = (collectionView的宽度 - 内边距与列间距) / 列数
CGFloat itemWidth = (collectionViewWidth - self.sectionInset.left - self.sectionInset.right - (self.columnCount - 1) * self.columnSpacing) / self.columnCount;
CGFloat itemHeight = 0;
//获取item的高度,由外界计算得到
if (self.itemHeightBlock) itemHeight = self.itemHeightBlock(itemWidth, indexPath);
else {
if ([self.delegate respondsToSelector:@selector(waterfallLayout:itemHeightForWidth:atIndexPath:)])
itemHeight = [self.delegate waterfallLayout:self itemHeightForWidth:itemWidth atIndexPath:indexPath];
}
//找出最短的那一列
__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;
//设置attributes的frame
attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight);
//更新字典中的最大y值
self.maxYDic[minIndex] = @(CGRectGetMaxY(attributes.frame));
return attributes;
}
//返回rect范围内item的attributes
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
return self.attributesArray;
}
@end