使用 Swift 创建分页 UICollectionView

Posted

技术标签:

【中文标题】使用 Swift 创建分页 UICollectionView【英文标题】:Create a Paging UICollectionView with Swift 【发布时间】:2015-07-11 08:42:48 【问题描述】:

我正在尝试创建一个带有分页的 UICollectionView,并且每个项目的最大宽度为 250 点,我已经设法创建它,但我有两个问题:第一个项目不是应该的那样开始,而是更多开始时有空格,当我尝试滑动时,总会有一些东西让我无法流畅地滑动。

看起来是这样的:

video link

这是我的代码:

CenterCellCollectionFlowLayout.swift

class CenterCellCollectionViewFlowLayout: UICollectionViewFlowLayout 

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? 

        var attributesToReturn:[UICollectionViewLayoutAttributes] = super.layoutAttributesForElementsInRect(rect) as! [UICollectionViewLayoutAttributes]

        for var i = 0 ; i < attributesToReturn.count ; i++
        
            var currentLayoutAttributes: UICollectionViewLayoutAttributes = attributesToReturn[i]
            var maximumSpacing: CGFloat = 50
            let origin: CGFloat
            if i - 1 >= 0 
                let previousLayoutAttributes = attributesToReturn[i - 1]
                origin = previousLayoutAttributes.frame.maxX
             else 
                origin = 0
            

            if origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize().width
            
                var frame: CGRect = currentLayoutAttributes.frame
                frame.origin.x = origin + maximumSpacing
                currentLayoutAttributes.frame = frame
            
        

        return attributesToReturn

    

    override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint 

        if let cv = self.collectionView 

            let cvBounds = cv.bounds
            let halfWidth = cvBounds.size.width * 0.5;
            let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidth;

            if let attributesForVisibleCells = self.layoutAttributesForElementsInRect(cvBounds) as? [UICollectionViewLayoutAttributes] 

                var candidateAttributes : UICollectionViewLayoutAttributes?
                for attributes in attributesForVisibleCells 

                    // == Skip comparison with non-cell items (headers and footers) == //
                    if attributes.representedElementCategory != UICollectionElementCategory.Cell 
                        continue
                    

                    if let candAttrs = candidateAttributes 

                        let a = attributes.center.x - proposedContentOffsetCenterX
                        let b = candAttrs.center.x - proposedContentOffsetCenterX

                        if fabsf(Float(a)) < fabsf(Float(b)) 
                            candidateAttributes = attributes;
                        

                    
                    else  // == First time in the loop == //

                        candidateAttributes = attributes;
                        continue;
                    


                

                return CGPoint(x : candidateAttributes!.center.x - halfWidth, y : proposedContentOffset.y);

            

        

        // Fallback
        return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
    

MainViewController.swift

class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout 

    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var collectionViewFlowLayout: CenterCellCollectionViewFlowLayout!

    var collectionObjects: NSMutableArray?
    private let reuseIdentifier = "CollectionViewCell"

    override func viewDidLoad() 
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    

    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
    
    

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
    
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell
        cell.backgroundColor = UIColor.greenColor()
        // Configure the cell
        return cell
    

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    
        return 10
    

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
    
        return UIEdgeInsetsMake(0, 0, 0, 0)
    

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
    
        return CGSizeMake(250, 250)
    

提前致谢

【问题讨论】:

【参考方案1】:

UICollectionView 继承自 UIScrollView。可以通过设置isPagingEnabled为true来实现分页。

【讨论】:

您刚刚使所有其他答案无效!为我工作,谢谢 天哪,伙计,我以为我需要重做所有收藏视图的工作,但你救了我的命!【参考方案2】:

所以我想出了怎么做。

首先创建一个自定义的 UICollectionViewFlowLayout 并添加这个覆盖这个方法:

override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint 

    if let cv = self.collectionView 

        let cvBounds = cv.bounds
        let halfWidth = cvBounds.size.width * 0.5;
        let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidth;

        if let attributesForVisibleCells = self.layoutAttributesForElementsInRect(cvBounds) as? [UICollectionViewLayoutAttributes] 

            var candidateAttributes : UICollectionViewLayoutAttributes?
            for attributes in attributesForVisibleCells 

                // == Skip comparison with non-cell items (headers and footers) == //
                if attributes.representedElementCategory != UICollectionElementCategory.Cell 
                    continue
                

                if let candAttrs = candidateAttributes 

                    let a = attributes.center.x - proposedContentOffsetCenterX
                    let b = candAttrs.center.x - proposedContentOffsetCenterX

                    if fabsf(Float(a)) < fabsf(Float(b)) 
                        candidateAttributes = attributes;
                    

                
                else  // == First time in the loop == //

                    candidateAttributes = attributes;
                    continue;
                


            

            return CGPoint(x : candidateAttributes!.center.x - halfWidth, y : proposedContentOffset.y);

        

    

    // Fallback
    return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)

然后在你实现 UICollectionView 的类上这样做:

    let collectionViewLayout: CenterCellCollectionViewFlowLayout = CenterCellCollectionViewFlowLayout()
    collectionViewLayout.itemSize = CGSizeMake(self.itemSize, self.itemSize)
    collectionViewLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    collectionViewLayout.minimumInteritemSpacing = 0
    collectionViewLayout.minimumLineSpacing = self.itemSpacing
    collectionViewLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal

    var collectionView: UICollectionView = UICollectionView(frame: self.collectionContainer.bounds, collectionViewLayout: collectionViewLayout)
    collectionView.delegate = self;
    collectionView.dataSource = self;
    collectionView.backgroundColor = UIColor.redColor()

    collectionView.registerClass(LevelsCustomCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    collectionView.registerNib(UINib(nibName: reuseIdentifier, bundle: nil), forCellWithReuseIdentifier: reuseIdentifier)

    self.collectionContainer.addSubview(collectionView)

就是这样,就像一个魅力。

【讨论】:

当你复制粘贴别人的代码时,你至少可以参考它:randexdev.com/2014/07/uicollectionview 这个代码对我来说比 karmadust 更好 工作就像一个魅力! 我想给予信任,但两个网站都无法正常工作。无论如何,我只是想帮助人们,而不是窃取某人的代码。 谢谢!对于我的用例,布局代码使单元格“对齐”到中心,这很棒。

以上是关于使用 Swift 创建分页 UICollectionView的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中使用分页向 UIScrollview 添加子视图

如何使用 MovieDB API Swift 为 TableView 进行分页?

使用 Swift 进行 Firebase Firestore 分页

使用 Firebase Firestore 进行分页 - swift 4

swift:如何使用 InfiniteScrolling 设置 UITableViewCell 显示全屏(允许分页)

如何在swift中使用alamofire和swiftyjson解析分页url?