Vinnicius Pereira
Vinnicius Pereira

Reputation: 57

How to center UICollectionviewCell with cell width different than the frame width and paging enable

I'm trying to center the uicollectionview cell while paging enable, but when I slide it, it does not stay centered! I would want it to be just like the image below!

        collectionView.dataSource = self
        collectionView.delegate = self

        collectionView.alwaysBounceHorizontal = true
        collectionView.isPagingEnabled = true

let collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let inset: CGFloat = calculateSectionIntet()
        return CGSize(width: view.frame.width - inset * 2, height: view.frame.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 16
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let inset: CGFloat = calculateSectionIntet()
        return UIEdgeInsets(top: 0, left: inset, bottom: 0 , right: inset)
    }

      func calculateSectionIntet() -> CGFloat {
            return 32
    }

Image:

The way it should be

Upvotes: 0

Views: 388

Answers (1)

Ajo
Ajo

Reputation: 386

Swift solution(Originally Objective-C) from a 2012 WWDC video.

Subclass UICollectionViewFlowLayout and override this function:

override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        guard let collectionView = collectionView else { return .zero }

        // Add some snapping behaviour so that the zoomed cell is always centered
        let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.frame.width, height: collectionView.frame.height)
        guard let rectAttributes = super.layoutAttributesForElements(in: targetRect) else { return .zero }

        var offsetAdjustment = CGFloat.greatestFiniteMagnitude
        let horizontalCenter = proposedContentOffset.x + collectionView.frame.width / 2

        for layoutAttributes in rectAttributes {
            let itemHorizontalCenter = layoutAttributes.center.x
            if (itemHorizontalCenter - horizontalCenter).magnitude < offsetAdjustment.magnitude {
                offsetAdjustment = itemHorizontalCenter - horizontalCenter
            }
        }

        return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
    }

Also for better snapping, add this to the collectionView's viewController: collectionView.decelerationRate = .fast

Upvotes: 1

Related Questions