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 installhttps://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.

