Skip to content

Commit a9be39f

Browse files
Merge pull request #5 from touchlane/columnsCount
Support different columns count
2 parents 64e2ca6 + 90f2880 commit a9be39f

File tree

3 files changed

+92
-96
lines changed

3 files changed

+92
-96
lines changed

Example/Source/ViewController.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class ViewController: UIViewController {
1818

1919
let backgroundColor = UIColor(red: 189 / 255, green: 195 / 255, blue: 199 / 255, alpha: 1)
2020

21+
let itemsInRow = 2
22+
var itemsInSection: [Int: Int] = [:]
23+
2124
override func viewDidLoad() {
2225
super.viewDidLoad()
2326
self.view.backgroundColor = backgroundColor
@@ -64,7 +67,12 @@ extension ViewController: UICollectionViewDataSource {
6467
}
6568

6669
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
67-
return 6
70+
if let numberOfItems = itemsInSection[section] {
71+
return numberOfItems
72+
}
73+
let numberOfItems = Int.random(in: 1...6)
74+
itemsInSection[section] = numberOfItems
75+
return numberOfItems
6876
}
6977

7078
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
@@ -89,7 +97,7 @@ extension ViewController: UICollectionViewDataSource {
8997

9098
extension ViewController: UICollectionViewDelegateFlowLayout {
9199
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
92-
let width = (collectionView.bounds.width - sectionInsets.left - sectionInsets.right - interitemSpacing) / 2
100+
let width = (collectionView.bounds.width - sectionInsets.left - sectionInsets.right - interitemSpacing * CGFloat(itemsInRow - 1)) / CGFloat(itemsInRow)
93101
return CGSize(width: width, height: width)
94102
}
95103

Source/CollapsedLayout.swift

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,16 @@ public class CollapsedLayout: UICollectionViewFlowLayout {
7979
let indexPath = IndexPath(row: row, section: section)
8080
let itemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
8181
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
82-
if row % 2 == 0 {
83-
attributes.frame = CGRect(
84-
x: self.sectionInset.left,
85-
y: contentHeight,
86-
width: itemSize.width,
87-
height: 0
88-
)
89-
}
90-
else {
91-
attributes.frame = CGRect(
92-
x: self.sectionInset.left + itemSize.width + self.minimumInteritemSpacing,
93-
y: contentHeight,
94-
width: itemSize.width,
95-
height: 0
96-
)
97-
}
82+
83+
let columnsCount = Int(contentWidth / itemSize.width)
84+
let column = row % columnsCount
85+
86+
attributes.frame = CGRect(
87+
x: sectionInset.left + CGFloat(column) * (itemSize.width + minimumInteritemSpacing),
88+
y: contentHeight,
89+
width: itemSize.width,
90+
height: 0
91+
)
9892
attributes.isHidden = true
9993
self.itemsAttributes[section].append(attributes)
10094
}

Source/ExpandedLayout.swift

Lines changed: 72 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -93,28 +93,23 @@ public class ExpandedLayout: UICollectionViewFlowLayout {
9393
let indexPath = IndexPath(row: row, section: section)
9494
let itemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
9595
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
96-
if row % 2 == 0 {
97-
attributes.frame = CGRect(
98-
x: self.sectionInset.left,
99-
y: contentHeight,
100-
width: itemSize.width,
101-
height: itemSize.height
102-
)
103-
}
104-
else {
105-
attributes.frame = CGRect(
106-
x: self.sectionInset.left + itemSize.width + self.minimumInteritemSpacing,
107-
y: contentHeight,
108-
width: itemSize.width,
109-
height: itemSize.height
110-
)
111-
}
96+
97+
let columnsCount = Int(contentWidth / itemSize.width)
98+
let column = row % columnsCount
99+
attributes.frame = CGRect(
100+
x: sectionInset.left + CGFloat(column) * (itemSize.width + minimumInteritemSpacing),
101+
y: contentHeight,
102+
width: itemSize.width,
103+
height: itemSize.height
104+
)
105+
112106
attributes.isHidden = false
113107
self.itemsAttributes[section].append(attributes)
114-
if row % 2 == 1 || row == numberOfItems - 1 {
108+
109+
if column == columnsCount - 1 || row == numberOfItems - 1 {
115110
self.contentHeight += itemSize.height
116111
if row < numberOfItems - 1 {
117-
contentHeight += self.minimumLineSpacing
112+
contentHeight += minimumLineSpacing
118113
}
119114
}
120115
}
@@ -203,8 +198,7 @@ public class ExpandedLayout: UICollectionViewFlowLayout {
203198
}
204199
return self.headersAttributes[indexPath.section]
205200
}
206-
207-
201+
208202
override public func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
209203
guard self.itemsAttributes.indices.contains(indexPath.section) else {
210204
return super.layoutAttributesForItem(at: indexPath)
@@ -229,7 +223,11 @@ public class ExpandedLayout: UICollectionViewFlowLayout {
229223
let numberOfItems = self.itemsAttributes[section].count
230224
for row in 0..<numberOfItems {
231225
let itemSize = self.itemsAttributes[section][row].frame.size
232-
if row % 2 == 1 || row == numberOfItems - 1 {
226+
227+
let columnsCount = Int(self.contentWidth / itemSize.width)
228+
let column = row % columnsCount
229+
230+
if column == columnsCount - 1 || row == numberOfItems - 1 {
233231
sectionContentHeight += itemSize.height
234232
targetOffset.y += itemSize.height
235233
if row < numberOfItems - 1 && itemSize.height > 0 {
@@ -306,27 +304,20 @@ public class ExpandedLayout: UICollectionViewFlowLayout {
306304
var itemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
307305
itemSize.height = visibleItemIndexPaths.contains(indexPath) ? itemSize.height : 0
308306
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
309-
310-
if row % 2 == 0 {
311-
attributes.frame = CGRect(
312-
x: self.sectionInset.left,
313-
y: contentHeight,
314-
width: itemSize.width,
315-
height: itemSize.height
316-
)
317-
}
318-
else {
319-
attributes.frame = CGRect(
320-
x: self.sectionInset.left + itemSize.width + self.minimumInteritemSpacing,
321-
y: contentHeight,
322-
width: itemSize.width,
323-
height: itemSize.height
324-
)
325-
}
307+
308+
let columnsCount = Int(self.contentWidth / itemSize.width)
309+
let column = row % columnsCount
310+
attributes.frame = CGRect(
311+
x: self.sectionInset.left + CGFloat(column) * (itemSize.width + self.minimumInteritemSpacing),
312+
y: contentHeight,
313+
width: itemSize.width,
314+
height: itemSize.height
315+
)
316+
326317
attributes.isHidden = false
327318
self.itemsAttributes[section].append(attributes)
328-
329-
if row % 2 == 1 || row == numberOfItems - 1 {
319+
320+
if column == columnsCount - 1 || row == numberOfItems - 1 {
330321
self.contentHeight += itemSize.height
331322
if !visibleItemIndexPaths.contains(indexPath) && section < targetSection {
332323
contentOffset.y -= previousItemsAttributes[section][row].frame.size.height
@@ -384,9 +375,7 @@ public class ExpandedLayout: UICollectionViewFlowLayout {
384375
}
385376
collectionView.setContentOffset(contentOffset, animated: false)
386377
}
387-
388-
389-
378+
390379
public func expandVisibleSections() {
391380
guard let collectionView = self.collectionView else {
392381
return
@@ -436,29 +425,22 @@ public class ExpandedLayout: UICollectionViewFlowLayout {
436425
var itemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
437426
itemSize.height = visibleItemIndexPaths.contains(indexPath) ? itemSize.height : 0
438427
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
439-
440-
if row % 2 == 0 {
441-
attributes.frame = CGRect(
442-
x: self.sectionInset.left,
443-
y: contentHeight,
444-
width: itemSize.width,
445-
height: itemSize.height
446-
)
447-
}
448-
else {
449-
attributes.frame = CGRect(
450-
x: self.sectionInset.left + itemSize.width + self.minimumInteritemSpacing,
451-
y: contentHeight,
452-
width: itemSize.width,
453-
height: itemSize.height
454-
)
455-
}
428+
429+
let columnsCount = Int(self.contentWidth / itemSize.width)
430+
let column = row % columnsCount
431+
attributes.frame = CGRect(
432+
x: self.sectionInset.left + CGFloat(column) * (itemSize.width + self.minimumInteritemSpacing),
433+
y: contentHeight,
434+
width: itemSize.width,
435+
height: itemSize.height
436+
)
437+
456438
attributes.isHidden = false
457439
// Sometimes cells overlap headers, the code below fixes it
458440
attributes.transform3D = CATransform3DMakeTranslation(0, 0, -1)
459441
self.itemsAttributes[section].append(attributes)
460-
461-
if row % 2 == 1 || row == numberOfItems - 1 {
442+
443+
if column == columnsCount - 1 || row == numberOfItems - 1 {
462444
self.contentHeight += itemSize.height
463445
if row < numberOfItems - 1 && visibleItemIndexPaths.contains(indexPath) {
464446
let nextIndexPath = IndexPath(row: indexPath.row + 1, section: indexPath.section)
@@ -503,8 +485,6 @@ public class ExpandedLayout: UICollectionViewFlowLayout {
503485

504486
private typealias ExpandedLayoutPrivate = ExpandedLayout
505487
private extension ExpandedLayoutPrivate {
506-
507-
508488
private func sectionHeadersPinToBoundsCorrection(proposedTopOffset: CGFloat,
509489
estimatedTopOffset: CGFloat) -> CGFloat {
510490
guard let collectionViewContentOffset = self.collectionView?.contentOffset.y,
@@ -518,7 +498,12 @@ private extension ExpandedLayoutPrivate {
518498
topOffsetCorrection = 0
519499
}
520500
else if proposedTopOffset - estimatedTopOffset <= collectionViewTopInset {
521-
topOffsetCorrection = proposedTopOffset - estimatedTopOffset
501+
if proposedTopOffset - collectionViewContentOffset >= collectionViewTopInset {
502+
topOffsetCorrection = proposedTopOffset - estimatedTopOffset
503+
} else {
504+
let newProposedTopOffset = proposedTopOffset - (collectionViewContentOffset - estimatedTopOffset)
505+
topOffsetCorrection = min(newProposedTopOffset, proposedTopOffset) - estimatedTopOffset
506+
}
522507
}
523508
else if proposedTopOffset - collectionViewContentOffset < collectionViewTopInset {
524509
topOffsetCorrection = proposedTopOffset - collectionViewContentOffset
@@ -529,8 +514,7 @@ private extension ExpandedLayoutPrivate {
529514
topOffsetCorrection = max(topOffsetCorrection, 0)
530515
return topOffsetCorrection
531516
}
532-
533-
517+
534518
private func determineVisibleIndexPaths() -> [IndexPath] {
535519
guard let collectionView = self.collectionView,
536520
let delegate = collectionView.delegate as? UICollectionViewDelegateFlowLayout,
@@ -561,10 +545,13 @@ private extension ExpandedLayoutPrivate {
561545
for row in 0..<numberOfItems {
562546
let indexPath = IndexPath(row: row, section: section)
563547
visibleItems.append(indexPath)
564-
let itemHeight = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath).height
565-
566-
if row % 2 == 1 || row == numberOfItems - 1 {
567-
visibleContentHeight += itemHeight
548+
let itemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
549+
550+
let columnsCount = Int(self.contentWidth / itemSize.width)
551+
let column = row % columnsCount
552+
553+
if column == columnsCount - 1 || row == numberOfItems - 1 {
554+
visibleContentHeight += itemSize.height
568555
if row < numberOfItems - 1 {
569556
visibleContentHeight += self.minimumLineSpacing
570557
}
@@ -582,10 +569,13 @@ private extension ExpandedLayoutPrivate {
582569
for row in 0..<numberOfItems {
583570
let indexPath = IndexPath(row: row, section: section)
584571
visibleItems.append(indexPath)
585-
let itemHeight = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath).height
586-
587-
if row % 2 == 1 {
588-
visibleContentHeight += itemHeight
572+
let itemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
573+
574+
let columnsCount = Int(self.contentWidth / itemSize.width)
575+
let column = row % columnsCount
576+
577+
if column == columnsCount - 1 {
578+
visibleContentHeight += itemSize.height
589579
if row > 0 {
590580
visibleContentHeight += self.minimumLineSpacing
591581
}
@@ -622,9 +612,13 @@ private extension ExpandedLayoutPrivate {
622612
let numberOfItems = dataSource.collectionView(collectionView, numberOfItemsInSection: section)
623613
for row in 0..<numberOfItems {
624614
let indexPath = IndexPath(row: row, section: section)
625-
let itemHeight = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath).height
626-
if row % 2 == 1 || row == numberOfItems - 1 {
627-
contentOffset += itemHeight
615+
let itemSize = delegate.collectionView!(collectionView, layout: self, sizeForItemAt: indexPath)
616+
617+
let columnsCount = Int(self.contentWidth / itemSize.width)
618+
let column = row % columnsCount
619+
620+
if column == columnsCount - 1 || row == numberOfItems - 1 {
621+
contentOffset += itemSize.height
628622
if row < numberOfItems - 1 {
629623
contentOffset += self.minimumLineSpacing
630624
}

0 commit comments

Comments
 (0)