EDCarousel is a UICollectionViewFlowLayout library for creating overlapping carousel-style collection views with smooth scaling animations.
- Animate cell scale while scrolling
- Configurable spacing modes (fixed & overlap)
- Customizable side-item scale, alpha, and shift
- Custom page control with image indicators
- Easy to integrate and use
- Supports both Swift Package Manager and CocoaPods
| Platform | Minimum Version |
|---|---|
| iOS | 14.0+ |
| Swift | 5.9+ |
| Xcode | 15.0+ |
Add EDCarousel to your project via Xcode:
- Go to File → Add Package Dependencies...
- Enter the repository URL:
https://github.com/emrdgrmnci/EDCarousel.git
- Select the version rule (e.g., Up to Next Major Version from
1.0.0) - Click Add Package
Or add it directly to your Package.swift:
dependencies: [ .package(url: "https://github.com/emrdgrmnci/EDCarousel.git", from: "1.0.0") ]
Then add EDCarousel to your target's dependencies:
.target( name: "YourTarget", dependencies: ["EDCarousel"] )
Add the following to your Podfile:
pod 'EDCarousel'
Then run:
pod install
https://github.com/emrdgrmnci/EDCarousel/tree/main/Example
Set the UICollectionView layout class to CarouselFlowLayout as shown below:
let layout = CarouselFlowLayout() layout.sideItemScale = 0.8 layout.sideItemAlpha = 0.8 layout.sideItemShift = 0.8 layout.spacingMode = .overlap(visibleOffset: 30) layout.scrollDirection = .horizontal layout.itemSize = CGSize(width: 250, height: 350) let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
let pageControl = CustomPageControl() pageControl.numberOfPages = 5 pageControl.currentPageImage = UIImage(systemName: "circle.fill") pageControl.otherPagesImage = UIImage(systemName: "circle")
Use scrollViewWillEndDragging to track the current page after scrolling:
func scrollViewWillEndDragging( _: UIScrollView, withVelocity _: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint> ) { let targetOffset = targetContentOffset.pointee.x let width = (collectionView.frame.size.width - padding) / 1.21 let rounded = Double((images.count / 2)) * abs(targetOffset / width) let scale = round(rounded) pageControl.currentPage = Int(scale) updateButtonStates(with: pageControl.currentPage) updateUI(with: pageControl.currentPage) }
// Previous page @IBAction func didTapOnPreviousButton(_: Any) { let prevIndex = max(pageControl.currentPage - 1, 0) let indexPath = IndexPath(item: prevIndex, section: 0) pageControl.currentPage = prevIndex collectionView?.isPagingEnabled = false collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true) } // Next page @IBAction func didTapOnNextButton(_: Any) { let nextIndex = min(pageControl.currentPage + 1, images.count - 1) let indexPath = IndexPath(item: nextIndex, section: 0) pageControl.currentPage = nextIndex collectionView?.isPagingEnabled = false collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true) }
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
// Register cell class collectionView.register(MyCell.self) // Register cell with nib file collectionView.registerNib(MyNibCell.self, bundle: nil) // Dequeue cell if let cell = collectionView.dequeue(MyCell.self, for: indexPath) { // Configure and use the dequeued cell }
Feel free to open an issue if you have questions about how to use EDCarousel, discovered a bug, or want to improve the implementation or interface.
EDCarousel is primarily the work of Emre Degirmenci.
EDCarousel is available under the MIT license. See the LICENSE file for more info.