UICollectionViewをPagingする１方法


#概要
UICollectionviewを`pagingEnable = true`でPage間のセルの位置ズレを発生させないでPagingする方法の紹介です。
![スクリーンショット 2015-07-22 1.49.11.png](https://qiita-image-store.s3.amazonaws.com/0/43254/50611b97-6c72-d84b-631e-80a340eae9ce.png)
![スクリーンショット 2015-07-22 1.49.14.png](https://qiita-image-store.s3.amazonaws.com/0/43254/ff5ab295-aa5b-3581-c900-8e24d8430bf7.png)


#現状の問題点
ページングしていくと、初期位置が少しずつずれていく(下図参照)。

![image0.png](https://qiita-image-store.s3.amazonaws.com/0/43254/8c64e33f-3e99-557f-a5cf-9404f99cc957.png)
![image1.png](https://qiita-image-store.s3.amazonaws.com/0/43254/825dadeb-0e22-aa1f-6eb8-46dd69b0c7af.png)

#制限事項
1セクションのみ対応です。

# 対応方法
UICollectionFlowLayoutクラスを継承したクラス内で毎回、layout処理を
行う。
処理の流れは以下
1)cellサイズを取得する。
2)表示ウインドウ内に収まるrow、column数を算出する。
3)x, y軸方向マージンを計算する。
x軸方向マージン = {コンテントサイズ.width - (cell幅 * column数) - (columnCont > 1 ? (columnCont - 1)*minimumLineSpacing}/2.0
y軸方向マージン = {コンテントサイズ.height - (cell高 * row数) - (rowCount > 1 ? (rowCount - 1) * minimumInteritemSpacing}/2.0

4)ページ毎indexを計算する。
index = セルindex%(rowCount*columnCount)
ページ内のrow,col番号　2行3列という感じで
row = index％rowCount
col = index/rowCount

5)配置位置を計算してCGRectでセットする。

6)ページング量を計算してorigin.xにセットする。

実装は以下

```swift
private func frameForItemAtIndexPath(indexPath: NSIndexPath) -> CGRect {
    // 1)
    let canvasSize = self.collectionView?.frame.size ?? CGSizeZero
    // 2)
    let rowCount =  floor((canvasSize.height - self.sectionInset.top - self.sectionInset.bottom) / (self.itemSize.height + self.minimumInteritemSpacing))
    let columnCont = floor((canvasSize.width - self.sectionInset.left - self.sectionInset.right) / (self.itemSize.width + self.minimumLineSpacing))
    // 3)
    let pageMarginX = (canvasSize.width - columnCont * self.itemSize.width - (columnCont > 1 ? (columnCont - 1) * self.minimumLineSpacing : 0)) / 2.0
    let pageMarginY = (canvasSize.height - rowCount * self.itemSize.height - (rowCount > 1 ? (rowCount - 1) * self.minimumInteritemSpacing : 0)) / 2.0
    // 4)
    let pageIndex = indexPath.row%Int(rowCount * columnCont)
    let row     = pageIndex % Int(rowCount)
    let column  = pageIndex / Int(rowCount)
    // 5)
    var cellFrame = CGRectZero
    cellFrame.origin.x  = pageMarginX + CGFloat(column) * (self.itemSize.width + self.minimumLineSpacing)
    cellFrame.origin.y  = pageMarginY + CGFloat(row) * (self.itemSize.height + self.minimumInteritemSpacing)
    cellFrame.size.width    = self.itemSize.width
    cellFrame.size.height   = self.itemSize.height
    // 6)
    if (self.scrollDirection == UICollectionViewScrollDirection.Horizontal) {
        let page = floor(CGFloat(indexPath.row)/(rowCount * columnCont))
        cellFrame.origin.x += canvasSize.width * page
    }
    
    return cellFrame
}
```


```swift
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
    let attr = super.layoutAttributesForItemAtIndexPath(indexPath)
    attr.frame = self.frameForItemAtIndexPath(indexPath)
    return attr
}

override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
    var attrs = [AnyObject]()
    if let originAttrs = super.layoutAttributesForElementsInRect(rect) {
        for var index = 0; index < self.collectionView?.numberOfItemsInSection(0); index++ {
            let indexPath = NSIndexPath(forRow: index, inSection: 0)
            let itemFrame = self.frameForItemAtIndexPath(indexPath)
            if CGRectIntersectsRect(itemFrame, rect) {
                let attr = self.layoutAttributesForItemAtIndexPath(indexPath)
                attrs.append(attr)
            }
        }
    }
    return attrs
}
```
ソースコードは[こちら](https://github.com/FuruyamaTakeshi/PagingCollectionView)
#参考サイト
[UICollectionView align logic missing in horizontal paging scrollview](http://stackoverflow.com/questions/13228600/uicollectionview-align-logic-missing-in-horizontal-paging-scrollview)