// // CustomCollectionViewLayout.swift // Product Calculator // // Created by Suraj Kumar Mandal on 09/12/21. // import UIKit class CustomCollectionViewLayout: UICollectionViewLayout { let numberOfColumns = 5 var shouldPinFirstColumn = true var shouldPinFirstRow = true var itemAttributes = [[UICollectionViewLayoutAttributes]]() var itemsSize = [CGSize]() var contentSize: CGSize = .zero override func prepare() { guard let collectionView = collectionView else { return } if collectionView.numberOfSections == 0 { return } if itemAttributes.count != collectionView.numberOfSections { generateItemAttributes(collectionView: collectionView) return } for section in 0.. UICollectionViewLayoutAttributes? { return itemAttributes[indexPath.section][indexPath.row] } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var attributes = [UICollectionViewLayoutAttributes]() for section in itemAttributes { let filteredArray = section.filter { obj -> Bool in return rect.intersects(obj.frame) } attributes.append(contentsOf: filteredArray) } return attributes } override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } } // MARK: - Helpers extension CustomCollectionViewLayout { func generateItemAttributes(collectionView: UICollectionView) { if itemsSize.count != numberOfColumns { calculateItemSizes() } var column = 0 var xOffset: CGFloat = 0 var yOffset: CGFloat = 0 var contentWidth: CGFloat = 0 itemAttributes = [] for section in 0.. contentWidth { contentWidth = xOffset } column = 0 xOffset = 0 yOffset += itemSize.height } } itemAttributes.append(sectionAttributes) } if let attributes = itemAttributes.last?.last { contentSize = CGSize(width: contentWidth, height: attributes.frame.maxY) } } func calculateItemSizes() { itemsSize = [] for index in 0.. CGSize { var text: NSString switch columnIndex { case 0: text = "MMM-99" default: text = "Content" } let size: CGSize = text.size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14.0)]) let width: CGFloat = size.width + 16 return CGSize(width: 150, height: 30) } }