forked from keighl/KTCenterFlowLayout
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKTCenterFlowLayout.m
117 lines (87 loc) · 4.15 KB
/
KTCenterFlowLayout.m
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
//
// KTCenterFlowLayout.m
//
// Created by Kyle Truscott on 10/9/14.
// Copyright (c) 2014 keighl. All rights reserved.
//
#import "KTCenterFlowLayout.h"
@interface KTCenterFlowLayout ()
@end
@implementation KTCenterFlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *superAttributes = [[NSMutableArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];
NSMutableDictionary *rowCollections = [NSMutableDictionary new];
id <UICollectionViewDelegateFlowLayout> flowDelegate = (id<UICollectionViewDelegateFlowLayout>) [[self collectionView] delegate];
BOOL delegateSupportsInteritemSpacing = [flowDelegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:)];
// Collect attributes by their midY coordinate.. i.e. rows!
for (UICollectionViewLayoutAttributes *itemAttributes in superAttributes)
{
// Normalize the midY to others in the row
// with variable cell heights the midYs can be ever so slightly
// different.
CGFloat midYRound = roundf(CGRectGetMidY(itemAttributes.frame));
CGFloat midYPlus = midYRound + 1;
CGFloat midYMinus = midYRound - 1;
NSNumber *key;
if (rowCollections[@(midYPlus)])
key = @(midYPlus);
if (rowCollections[@(midYMinus)])
key = @(midYMinus);
if (!key)
key = @(midYRound);
if (!rowCollections[key])
rowCollections[key] = [NSMutableArray new];
[(NSMutableArray *) rowCollections[key] addObject:itemAttributes];
}
CGFloat collectionViewWidth = CGRectGetWidth(self.collectionView.bounds) - self.collectionView.contentInset.left - self.collectionView.contentInset.right;
// Adjust the items in each row
[rowCollections enumerateKeysAndObjectsUsingBlock:^(id key, NSArray *itemAttributesCollection, BOOL *stop) {
NSInteger itemsInRow = [itemAttributesCollection count];
// x-x-x-x ... sum up the interim space
CGFloat interitemSpacing = [self minimumInteritemSpacing];
// Check for delegate support
if (delegateSupportsInteritemSpacing && itemsInRow > 0)
{
NSInteger section = [[itemAttributesCollection[0] indexPath] section];
interitemSpacing = [flowDelegate collectionView:self.collectionView
layout:self
minimumInteritemSpacingForSectionAtIndex:section];
}
CGFloat aggregateInteritemSpacing = interitemSpacing * (itemsInRow -1);
// Sum the width of all elements in the row
CGFloat aggregateItemWidths = 0.f;
for (UICollectionViewLayoutAttributes *itemAttributes in itemAttributesCollection)
aggregateItemWidths += CGRectGetWidth(itemAttributes.frame);
// Build an alignment rect
// |==|--------|==|
CGFloat alignmentWidth = aggregateItemWidths + aggregateInteritemSpacing;
CGFloat alignmentXOffset = (collectionViewWidth - alignmentWidth) / 2.f;
// Adjust each item's position to be centered
CGRect previousFrame = CGRectZero;
for (UICollectionViewLayoutAttributes *itemAttributes in itemAttributesCollection)
{
CGRect itemFrame = itemAttributes.frame;
if (CGRectEqualToRect(previousFrame, CGRectZero))
itemFrame.origin.x = alignmentXOffset;
else
itemFrame.origin.x = CGRectGetMaxX(previousFrame) + interitemSpacing;
itemAttributes.frame = itemFrame;
previousFrame = itemFrame;
}
}];
return superAttributes;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *superAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
// Rect that encompasses all items on indexPath's line.
CGRect lineRect = CGRectMake(0.0, CGRectGetMinY(superAttributes.frame), CGRectGetWidth(self.collectionView.frame), CGRectGetHeight(superAttributes.frame));
NSArray *lineAttributes = [self layoutAttributesForElementsInRect:lineRect];
for (UICollectionViewLayoutAttributes *itemAttributes in lineAttributes) {
if (itemAttributes.indexPath == indexPath) {
return itemAttributes;
}
}
return nil;
}
@end