2015-07-11 32 views
3

我試圖創建一個帶分頁的UICollectionView,並且每個項目的最大寬度都是250分,我已經設法創建它,但我遇到了2個問題:第一個項目不是因爲它應該是,但是在開始的時候有更多的空間,當我嘗試滑動時,總會有東西不會讓我滑動。使用Swift創建分頁UICollectionView

這是它的外觀:

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) 
    } 
} 

在此先感謝

回答

8

所以我想出如何做到這一點。

首先創建一個自定義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) 

那一下,就像一個魅力。

+13

當您複製粘貼其他人的代碼時,您至少可以引用它:https://randexdev.com/2014/07/uicollectionview/ – Benjamin

+1

http://blog.karmadust.com/centered-paging-with-preview -cells-on-uicollectionview/ –

+0

這段代碼對我來說比karmadust更好用 –