如何使用 UICollectionViewFlowLayout 将集合中的每个视图居中?

How to center each view in the collection with UICollectionViewFlowLayout?

这里也有类似的问题,不过问题出在我的代码上,不知道如何解决。

我不知道为什么,但是当我滚动 collectionview 时,单元格向左移动得更多。见下图:

这是我的 UICollectionViewFlowLayout 的代码

import UIKit

class PrayerFlowLayout: UICollectionViewFlowLayout {
    //let standardItemAlpha: CGFloat = 0.3
    let standardItemScale: CGFloat = 0.85

    var isSetup = false

    override func prepare() {
        super.prepare()
        if isSetup == false {
            setupCollectionView()
            isSetup = true
        }
    }

    override open func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect)
        var attributesCopy = [UICollectionViewLayoutAttributes]()

        for itemAttributes in attributes! {
            let itemAttributesCopy = itemAttributes.copy() as! UICollectionViewLayoutAttributes

            changeLayoutAttributes(itemAttributesCopy)
            attributesCopy.append(itemAttributesCopy)
        }

        return attributesCopy
    }


    // indicates the point on where to stop scrolling each prayer
    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        // get layout attribute to use to make some calculations
        let layoutAttributes = self.layoutAttributesForElements(in: collectionView!.bounds)

        // get the horizontal center on the collection
        let center = collectionView!.frame.size.width / 2

        // add the center to the proposed content offset
        let proporsedContentOffsetCenterOrigin = proposedContentOffset.x + center

        let closest = layoutAttributes!.sorted {
            abs([=10=].center.x - proporsedContentOffsetCenterOrigin) < abs(.center.x - proporsedContentOffsetCenterOrigin)
            }.first ?? UICollectionViewLayoutAttributes()

        let targetContentOffset = CGPoint(x: floor(closest.center.x - center), y: proposedContentOffset.y - center)

        return targetContentOffset
    }

    func changeLayoutAttributes(_ attributes: UICollectionViewLayoutAttributes) {
        let collectionCenter = collectionView!.bounds.width / 2
        let offset = collectionView!.contentOffset.x
        let normalizedCenter = attributes.center.x - offset

        let maxDistance = collectionView!.bounds.size.width + self.minimumLineSpacing
        //collectionView!.frame.width + self.minimumLineSpacing // self.itemSize.width + self.minimumLineSpacing
        let distance = min(abs(collectionCenter - normalizedCenter), maxDistance)

        let ratio = (maxDistance - distance)/maxDistance

        //let alpha = ratio * (1 - self.standardItemAlpha) + self.standardItemAlpha
        let scale = ratio * (1 - self.standardItemScale) + self.standardItemScale

        //attributes.alpha = alpha
        attributes.transform3D = CATransform3DScale(CATransform3DIdentity, scale, scale, 1)
    }


    func setupCollectionView() {
        self.collectionView!.decelerationRate = UIScrollView.DecelerationRate.fast

        let collectionSize = collectionView!.bounds.size
        let yInset = (collectionSize.height - self.itemSize.height) / 3
        let xInset = (collectionSize.width - self.itemSize.width) / 2

        let topPos = (collectionView!.bounds.height - (collectionView!.bounds.height - 75) )

        self.sectionInset = UIEdgeInsets.init(top: topPos, left: xInset, bottom: yInset, right: xInset)
    }

}

关于如何让所有单元格始终居中有什么想法吗?

你需要像这样使用UICollectionViewDelegateFlowLayout方法

class CardListViewController:UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{

    // UICollectionViewDelegateFlowLayout Delegate method

   func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
        let leftAndRightPaddings: CGFloat = 20.0
        let numberOfItemsPerRow: CGFloat = 1.0

        let width = (collectionView.frame.width - leftAndRightPaddings)/numberOfItemsPerRow
        return CGSize(width: width, height: collectionView.frame.width)

    }
}

像这样从故事板集部分插入。

输出: