How to add PageControl inside UICollectionView Image Scrolling - ios

I have UICollectionView Horizontal Image listing code. I want to add PageControl when scrolling images will shows, I added pagecontrol selector and IBOutlet but how can I integrate it between UICollecitonView?
My code is below:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var View : DesignableView!
#IBOutlet var collectionView: UICollectionView!
#IBOutlet var collectionViewLayout: UICollectionViewFlowLayout!
#IBOutlet open weak var pageControl: UIPageControl? {
didSet {
pageControl?.addTarget(self, action: #selector(ViewController.pageChanged(_:)), for: .valueChanged)
}
}
override func viewDidLoad() {
super.viewDidLoad()
pageControl?.numberOfPages = 11
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 11;
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: ImageCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
cell.label.text = "Cell \(indexPath.row)"
cell.backgroundImageView.image = UIImage(named: "Parallax \(indexPath.row + 1)")
// Parallax cell setup
cell.parallaxTheImageViewScrollOffset(self.collectionView.contentOffset, scrollDirection: self.collectionViewLayout.scrollDirection)
return cell
}
#IBAction open func pageChanged(_ sender: UIPageControl) {
print(sender.currentPage)
}
// MARK: Delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return collectionView.bounds.size;
}
// MARK: Scrolling
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// Parallax visible cells
for cell: ImageCollectionViewCell in collectionView.visibleCells as! [ImageCollectionViewCell] {
cell.parallaxTheImageViewScrollOffset(self.collectionView.contentOffset, scrollDirection: self.collectionViewLayout.scrollDirection)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

I'm not a fan of the accepted answer. From time to time, willDisplay cell will return the wrong page for the page control depending on users interaction.
What I use:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
}
This will update the page after the user has finished scrolling thus making the currentPage of the pageControl more accurate.

Here you have a complete class with Page Control pagination in a horizontal collection view.
This is working on one of my applications, right now, and is working correctly. If you cannot get it work, do feel free to ask me and I'll help you.
First, in the Storyboard you have to set up your CollectionView with:
Layout: Flow
Scroll Direction: Horizontal
Scrolling enabled
Paging enabled
#IBOutlet weak var collectionView: UICollectionView! //img: 77
#IBOutlet weak var pageControl: UIPageControl!
var thisWidth:CGFloat = 0
override func awakeFromNib() {
super.awakeFromNib()
thisWidth = CGFloat(self.frame.width)
collectionView.delegate = self
collectionView.dataSource = self
pageControl.hidesForSinglePage = true
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
self.pageControl.currentPage = indexPath.section
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
thisWidth = CGFloat(self.frame.width)
return CGSize(width: thisWidth, height: self.frame.height)
}

For a more responsive UIPageControl, I prefer to use scrollViewDidScroll and calculating the offset with regards to the horizontal center of the scrollView.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offSet = scrollView.contentOffset.x
let width = scrollView.frame.width
let horizontalCenter = width / 2
pageControl.currentPage = Int(offSet + horizontalCenter) / Int(width)
}

Swift 5 Very Smooth working
//MARK:- For Display the page number in page controll of collection view Cell
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: self.collectionview.contentOffset, size: self.collectionview.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = self.collectionview.indexPathForItem(at: visiblePoint) {
self.pageControl.currentPage = visibleIndexPath.row
}
}

Waiting for scrollViewDidEndDecelerating results in a slow update to the UIPageControl. If you want a more responsive UI, I suggest instead implementing scrollViewWillEndDragging(_:withVelocity:targetContentOffset:).
Swift 4 example where each collection view section is a page:
override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if let collectionView = scrollView as? ScoreCollectionView,
let section = collectionView.indexPathForItem(at: targetContentOffset.pointee)?.section {
self.pageControl.currentPage = section
}
}

swift 5 example:
function to set pageController CurrentPage according to Index of CollectionView:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = self.collectionView.indexPathForItem(at: visiblePoint) {
self.pageController.currentPage = visibleIndexPath.row
}
}
PageControllerAction function to scroll CollectionView on selecting PageController :
#IBAction func pageControllerAction(_ sender: UIPageControl) {
self.collectionView.scrollToItem(at: IndexPath(row: sender.currentPage, section: 0), at: .centeredHorizontally, animated: true)
}

Luke's answer was a good start for me but it had two issues: it didn't update frequently (already noted in other answers) but most importantly it didn't show the correct page for the last item in my collection view (horizontally oriented) and it only switched page when the item was almost leaving the screen.
For the first issue, as others noted, using scrollViewDidScroll provided a better experience. I was concerned about performance issues for making the call so frequently but didn't notice any.
As for the second issue, for my use case, finding the indexPath of the cell that is at the center of the screen provided a better solution. Keep in mind that if your use case can fit more than two cells on screen this may need to be adjusted. This is because your last cell would never reach the middle of the screen. I would argue though that in that case using the UIPageControl might not be ideal anyway.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = self.collectionView.indexPathForItem(at: visiblePoint) {
self.pageControl.currentPage = visibleIndexPath.row
}
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: self.cvImageListing.contentOffset, size: self.cvImageListing.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = self.cvImageListing.indexPathForItem(at: visiblePoint) {
self.pageControl.currentPage = visibleIndexPath.row
}
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let OFFSet = scrollView.contentOffset.x
let width = scrollView.frame.width
let horizontalCenter = width / 2
pageviewControl.currentPage = Int(OFFSet + horizontalCenter) / Int(width)
}

This seems to work for me:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let x = targetContentOffset.pointee.x
pageControl.currentPage = Int(x / view.frame.width)
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = scrollView.frame.size.width
let currP = Int(floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1)
if self.pageC.currentPage != currP {
self.pageC.currentPage = currP
}
}

Simply add this function
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView){
//Test the offset and calculate the current page after scrolling ends
let pageWidth:CGFloat = scrollView.frame.width
let currentPage:CGFloat = floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1
//Change the indicator
self.pageControl.currentPage = Int(currentPage);
}

Related

UICollectionView custom cell UILabel missing when UIImageView has image

I have problems using Custom UICollectionViewCell. Custom cell has one UILabel and one UIImageView. The problem is, when I put image on UIImageView(Left screenshot), UILabel in same cell disappears like picture below. But if there's no Image source on UIImageView, UILabel is not missing.
This is code for Viewcontroller which has UICollectionView
class CatTowerVeiwController: UIViewController {
#IBOutlet weak var popCountSwitch: UISwitch!
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let switchState = UserDefaults.standard.bool(forKey: UserDataKey.popCountVisibility)
popCountSwitch.setOn(switchState, animated: false)
collectionView.register(UINib(nibName: "CatTowerCell", bundle: nil), forCellWithReuseIdentifier: "cell")
setupFlowLayout(numberOfCells: 2.0)
}
#IBAction func doneButtonClicked(_ sender: UIButton) {
let isLabelVisible = self.popCountSwitch.isOn
UserDefaults.standard.set(isLabelVisible, forKey: UserDataKey.popCountVisibility)
self.dismiss(animated: false)
}
}
extension CatTowerVeiwController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CatTowerCell
// cell.cellImage.image = #imageLiteral(resourceName: "popcat_closed")
cell.cellName.text = "Popcat"
print(cell.cellName.frame.size.height)
print(cell.cellName.frame.size.width)
return cell
}
}
extension CatTowerVeiwController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let leftAndRightPaddings: CGFloat = 45.0
let numberOfItemsPerRow: CGFloat = 2.0
let width = (collectionView.frame.width-leftAndRightPaddings)/numberOfItemsPerRow
return CGSize(width: width, height: width)
}
private func setupFlowLayout(numberOfCells: CGFloat) {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
let halfWidth = UIScreen.main.bounds.width / numberOfCells
flowLayout.itemSize = CGSize(width: halfWidth * 0.8 , height: halfWidth * 0.8)
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = halfWidth * 0.1
self.collectionView.collectionViewLayout = flowLayout
}
}
And this is code for custom cell
class CatTowerCell: UICollectionViewCell {
#IBOutlet weak var cellImage: UIImageView!
#IBOutlet weak var cellName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
This is what I trying to make:
The solution was Compression Priority
The height of UILabel became 0 because UIImageView is too big
My solution is setting Vertical compression Priority of UILabel larger than UIImageView.
Pin your imageview's bottom anchor constraint to the label's top anchor.
And make sure there are no conflicting constraints.
label.topAnchor.constraint(equalTo: imageview.bottomAnchor).isActive = true

Why is the CollectionView function called twice in Swift?

I am having trouble with the function being called 2 times. Because of this, the value in PageView is not set properly because the index value is not correct. How can you control this correctly?
ViewController.swift
class ViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var pageView: UIPageControl!
#IBOutlet var guideView: UIView!
var step : Int! = 0
var beforeStep : Int! = 0
var imageArray = [UIImage(named: "swipe1"),
UIImage(named: "swipe2"),
UIImage(named: "swipe3"),
UIImage(named: "swipe4"),
UIImage(named: "swipe5")]
override func viewDidLoad() {
super.viewDidLoad()
pageView.numberOfPages = imageArray.count
pageView.currentPage = 0
pageView.currentPageIndicatorTintColor = UIColor.color(.dacColor)
pageView.pageIndicatorTintColor = UIColor.gray
view.backgroundColor = UIColor(red: CGFloat(252.0/255.0), green: CGFloat(251.0/255.0), blue: CGFloat(245.0/255.0), alpha: CGFloat(1.0))
collectionView.backgroundColor = UIColor(red: CGFloat(252.0/255.0), green: CGFloat(251.0/255.0), blue: CGFloat(245.0/255.0), alpha: CGFloat(1.0))
}
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if let vc = cell.viewWithTag(111) as? UIImageView {
vc.image = imageArray[indexPath.row]
}
if let ab = guideView.viewWithTag(222) as? UIPageControl {
ab.currentPage = indexPath.row - 1
}
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = collectionView.frame.size
return CGSize(width: size.width, height: size.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
problematic function part
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if let vc = cell.viewWithTag(111) as? UIImageView {
vc.image = imageArray[indexPath.row]
}
if let ab = guideView.viewWithTag(222) as? UIPageControl {
ab.currentPage = indexPath.row - 1
}
return cell
}
CollectionView in StoryBoard
View List in Storyboard
I want the PageController to be marked to match the location of the picture.
Has anyone solved the same problem as me?
collectionView(_:cellForItemAt:) is a collection view delegate method which tends to get called more than once, and there are a lot of factors that trigger the call like:
The number of visible cells you've got, depending on the height of the collection
When scrolling through cells to reuse them
Or triggers to change/refresh the collection like:
reloadData(), reloadItems(at:) or reloadSections(_:)
Perhaps a layoutIfNeeded() call from the view that contains this collection view.
and more...
The point is, the function getting called more than once is pretty normal. Your answer probably lies in "What triggers the call?"
EDIT:
To update your pageControl according to the index of the collection:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: yourCollectionView.contentOffset, size: yourCollectionView.bounds.size)
let midPointOfVisibleRect = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = yourCollectionView.indexPathForItem(at: midPointOfVisibleRect) {
yourPageControl.currentPage = visibleIndexPath.row
}
}
If you're using a UIPageViewController just for the page indication, a UIPageControl should do. You might also have to set yourCollectionView.isPagingEnabled = true as that would be more appropriate for a page control.
In collection view go to layout and select custom:
class CustomCollectionViewFlowLayout: UICollectionViewFlowLayout
{
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint
{
if let collectionViewBounds = self.collectionView?.bounds
{
let halfWidthOfVC = collectionViewBounds.size.width * 0.5
let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidthOfVC
if let attributesForVisibleCells = self.layoutAttributesForElements(in: collectionViewBounds)
{
var candidateAttribute : UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells
{
let candAttr : UICollectionViewLayoutAttributes? = candidateAttribute
if candAttr != nil
{
let a = attributes.center.x - proposedContentOffsetCenterX
let b = candAttr!.center.x - proposedContentOffsetCenterX
if fabs(a) < fabs(b)
{
candidateAttribute = attributes
}
}
else
{
candidateAttribute = attributes
continue
}
}
if candidateAttribute != nil
{
return CGPoint(x: candidateAttribute!.center.x - halfWidthOfVC, y: proposedContentOffset.y);
}
}
}
return CGPoint.zero
}
}
and then in delegate:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.origin = Collections.contentOffset
visibleRect.size = Collections.bounds.size
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
guard let indexPath = Collections.indexPathForItem(at: visiblePoint) else { return }
print(indexPath.item)
}

I want create this Sliding UIVies in xcode using swift, what sholud i used ? an collecntionView or TableView?

i want to create an exact screen in my ios application with xcode & swift im not able to create it, what shall i used? an collectionView or ScroolView?
import UIKit
class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
#IBOutlet weak var newCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
newCollectionView.delegate = self
newCollectionView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
It is my class. It works completely. Also i added an image of storyboard. Link to my github project : https://github.com/Agisight/scroller.git
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scroll: UIScrollView!
#IBOutlet var btns: [UIView]!
override func viewDidLoad() {
super.viewDidLoad()
scroll.delegate = self
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
methodAnimation()
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
methodAnimation()
}
func methodAnimation() {
if btns.count == 0 {return}
var i = 0
// i – calculate it, it is your visible/desirable view.
// here is variant of code
let dragOffset = view.frame.width * 0.5 // callibrate it for you
let offX = scroll.contentOffset.x
i = Int(offX + dragOffset) / Int(view.frame.width)
i = max(0, min(i, btns.count - 1))
let yourX = btns[i].frame.width * CGFloat(i) // ()
let p = CGPoint(x: yourX, y: 0);
scroll.setContentOffset(p, animated: true)
}
}

Get updated IndexPath for visible item after UICollectionView has scrolled

I have a collectionView with different periods (day to year) for user to choose. Each item's size is equal to the size of collectionView itself.
#IBOutlet weak var periodCollectionView: UICollectionView!
#IBOutlet weak var itemLabel: UILabel!
let collectionValues = ["Day", "Week", "Month", "Year"]
var currentVisibleItem: Int?
override func viewDidLoad() {
super.viewDidLoad()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PeriodName", for: indexPath) as? DisplayPeriodCollectionViewCell
else {
fatalError("Unable to cast collection view cell as DisplayPeriodCollectionViewCell")
}
cell.periodName.text = collectionValues[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = collectionView.frame.height
let width = collectionView.frame.width
return CGSize(width: width, height: height)
}
What i am trying to do is get an info label to display the index of current visible item after collectionView has scrolled. Her is the code:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let centerPoint = CGPoint(x: periodCollectionView.center.x + periodCollectionView.contentOffset.x, y: 1.0)
print("centerPoint: \(centerPoint)")
if let currentItemIndexPath = periodCollectionView.indexPathForItem(at: centerPoint) {
currentVisibleItem = currentItemIndexPath.item
print("index of current item: \(currentVisibleItem!)")
itemLabel.text = "\(currentVisibleItem!)"
} else {
print("could not get index of current item...")
}
}
I've added print statements to check if values are defined correctly at runtime, and they show everything is fine. The problem is that label does not always update its text after scrolling ends, but instead waits for new scrolling to occur:
I can't figure out why this is happening - setting a breakpoint at scrollViewDidEndDecelerating shows that all code gets executed, so what's wrong with the label text?
UPD. Not-updating label text appears to be a Simulator issue - when running on device, label updates correctly.
Try this
override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let currentIndex = scrollView.contentOffset.x / CGFloat((itemWidth + interitemSpacing / 2))
print(currentIndex)
}
Please try the following code.
I used this many times in my real projects and this works fine.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let visibleIndex = Int(targetContentOffset.pointee.x / collectionView.frame.width)
print(visibleIndex)
}
In your case you can use:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
because each item is at the same size as your collection view.
if you still want to use scroll view delegate you should write your page calculation in the following delegate functions:
func scrollViewDidEndDragging(UIScrollView, willDecelerate: Bool)
func scrollViewDidEndDecelerating(UIScrollView)
func scrollViewDidEndScrollingAnimation(UIScrollView)

Swift - How to bringSubviewToFront of tableview cell which at the center of horizontal carousal

I have created a caurosal as per the below screen
On scrolling i m using scrollViewWillEndDragging to center the tableview cell. But i dont know how to increase the z-index or bringSubviewToFront of the center of tablecellview. when i scroll next cell will be bring to front and existing cell will remove its bringtofront properties
below is view controller code which i have written:
import UIKit
class CarouselViewController: UIViewController,UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
var nos_images = ["One","Two","Three","Four","One","Two","Three","Four","One","Two","Three","Four","One","Two","Three","Four"]
let cellscaling: CGFloat = 0.6
override func viewDidLoad() {
super.viewDidLoad()
let screensize = UIScreen.main.bounds.size
let cellwidth = floor(screensize.width * cellscaling)
let cellheight = floor(screensize.height * cellscaling)
let insetX = (view.bounds.width - cellwidth) / 2.0
let insetY = (view.bounds.height - cellwidth) / 2.0
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: cellwidth, height: cellheight)
collectionView.contentInset = UIEdgeInsetsMake(insetY, insetX, insetY, insetX)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return nos_images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cellIdentifier = "caurosalcell"
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier,
for: indexPath) as! CaurosalCollectionViewCell
cell.featureImage.image = UIImage(named: nos_images[indexPath.row])
cell.title.text = nos_images[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
print(indexPath.row)
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let layout = self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
let cellWidthIncludingSpacing = layout.itemSize.width + layout.minimumLineSpacing
var offset = targetContentOffset.pointee
let index = (offset.x + scrollView.contentInset.left) / cellWidthIncludingSpacing
let roundIndex = round(index)
offset = CGPoint(x: roundIndex * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
targetContentOffset.pointee = offset
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
expected out should be like this image

Resources