Last active
August 9, 2024 21:06
-
-
Save kmikael/53a031c5ec421ae43ceff7237f5d8f5b to your computer and use it in GitHub Desktop.
Snapping, centering and automatically sizing flow layout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class HomeCollectionViewFlowLayout: UICollectionViewFlowLayout { | |
var isSetUp = false | |
override func prepare() { | |
super.prepare() | |
setUpIfNeeded() | |
} | |
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { | |
let targetContentOffset = super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) | |
guard let collectionView = collectionView, let layoutAttributes = layoutAttributesForElements(in: collectionView.bounds) else { | |
return targetContentOffset | |
} | |
let centerX = collectionView.bounds.width / 2.0 | |
let z = proposedContentOffset.x + centerX | |
guard let first = layoutAttributes.sorted(by: { abs($0.center.x - z) < abs($1.center.x - z) }).first else { | |
return targetContentOffset | |
} | |
return CGPoint(x: first.center.x - centerX, y: proposedContentOffset.y) | |
} | |
} | |
extension HomeCollectionViewFlowLayout { | |
func setUpIfNeeded() { | |
guard let collectionView = collectionView, !isSetUp else { | |
return | |
} | |
collectionView.decelerationRate = UIScrollViewDecelerationRateFast | |
collectionView.showsHorizontalScrollIndicator = false | |
collectionView.showsVerticalScrollIndicator = false | |
scrollDirection = .horizontal | |
minimumLineSpacing = 25.0 | |
minimumInteritemSpacing = 0.0 | |
if layoutAttributesForElements(in: collectionView.bounds)?.count == 1 { | |
itemSize = collectionView.bounds.insetBy(dx: 25.0, dy: 25.0).size | |
} else { | |
itemSize = collectionView.bounds.insetBy(dx: 50.0, dy: 25.0).size | |
} | |
let leftRight = (collectionView.bounds.width - itemSize.width) / 2.0 | |
sectionInset = UIEdgeInsets(top: 0.0, left: leftRight, bottom: 0.0, right: leftRight) | |
invalidateLayout() | |
isSetUp = true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment