Skip to content

Instantly share code, notes, and snippets.

@gunantosteven
Created April 30, 2020 15:44
Show Gist options
  • Save gunantosteven/92dfbeab86b303c4e7f90a1f35d2568d to your computer and use it in GitHub Desktop.
Save gunantosteven/92dfbeab86b303c4e7f90a1f35d2568d to your computer and use it in GitHub Desktop.
Create UICollectionView Like Instagram When Exploring Photos
import UIKit
class SavedCollectionViewLayout: UICollectionViewLayout {
private let columnsCount = 18 // 18 type columns
private let numberOfColumns = CGFloat(3.0)
private let minimumLineSpacing: CGFloat = 2
private let minimumInteritemSpacing: CGFloat = 2
private var cache: [UICollectionViewLayoutAttributes] = []
private var contentHeight: CGFloat = 0
private var contentWidth: CGFloat {
guard let collectionView = collectionView else {
return 0
}
let insets = collectionView.contentInset
return collectionView.bounds.width - (insets.left + insets.right)
}
override var collectionViewContentSize: CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
private var columnWidth: CGFloat {
return contentWidth / numberOfColumns
}
override func prepare() {
guard
cache.isEmpty,
let collectionView = collectionView
else {
return
}
var yOffsetNext = CGFloat(0.0)
for item in 0..<collectionView.numberOfItems(inSection: 0) {
let indexPath = IndexPath(item: item, section: 0)
var xOffset = CGFloat(0.0), yOffset = CGFloat(yOffsetNext)
let rowColumn = indexPath.row % columnsCount
// handle x position
if (rowColumn == 1) || (rowColumn == 4) || (rowColumn == 7) || (rowColumn == 13)
|| (rowColumn == 16) {
xOffset = CGFloat(columnWidth)
} else if (rowColumn == 5) || (rowColumn == 8) || (rowColumn == 10) || (rowColumn == 11)
|| (rowColumn == 14) || (rowColumn == 17) {
xOffset = CGFloat(columnWidth * 2)
}
// handle y position for the next column
if (rowColumn == 1) || (rowColumn == 2) || (rowColumn == 5) || (rowColumn == 8)
|| (rowColumn == 10) || (rowColumn == 11) || (rowColumn == 14) || (rowColumn == 17) {
yOffsetNext += columnWidth + minimumLineSpacing
}
// handle width and height
let size = getSizeColumn(indexPath: indexPath)
let frame = CGRect(x: xOffset,
y: yOffset,
width: size.width,
height: size.height)
contentHeight = max(contentHeight, frame.maxY)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = frame
cache.append(attributes)
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
// Loop through the cache and look for items in the rect
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
return visibleLayoutAttributes
}
override func layoutAttributesForItem(at indexPath: IndexPath)
-> UICollectionViewLayoutAttributes? {
return cache[indexPath.item]
}
func emptyCache() {
self.cache.removeAll()
}
func getSizeColumn(indexPath: IndexPath) -> CGSize {
let rowColumn = indexPath.row % columnsCount
var height = CGFloat(0.0), width = CGFloat(0.0)
if rowColumn == 1 {
width = CGFloat(columnWidth * 2)
height = CGFloat(columnWidth * 2) + minimumLineSpacing
} else if (rowColumn == 5) || (rowColumn == 8) || (rowColumn == 10)
|| (rowColumn == 11) || (rowColumn == 14) || (rowColumn == 17) {
width = CGFloat(columnWidth)
height = CGFloat(columnWidth)
} else if rowColumn == 9 {
width = CGFloat(columnWidth * 2) - minimumInteritemSpacing
height = CGFloat(columnWidth * 2) + minimumLineSpacing
} else {
width = CGFloat(columnWidth) - minimumInteritemSpacing
height = CGFloat(columnWidth)
}
return CGSize(width: width, height: height)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment