tah nn

主にアプリ開発の技術メモを残していきます。

【Objective-C】UICollectionViewでのページスクロール

UICollectionViewをページスクロールにしたいときのメモです。
(環境:xcode5.1.1, iOS 7.1)

pagingEnabled = YES とすればできますが、各セルの間に間隔をいれたいときは、これだと表示位置がずれていってしまいます。
そこで、UICollectionViewFlowLayout (UICollectionViewのレイアウトをカスタマイズできるクラス) を継承したクラスを作成し、セルが画面の中央に常にくるように処理を書きます。

targetContentOffsetForProposedContentOffset::メソッドをオーバーライドします。
下記の例は、1列のシンプルなコレクションビューで、セルの真ん中(x軸)が画面の真ん中にくるように設定しています。

/*HogeCollectionViewFlowLayout.m*/

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
    CGFloat offsetAdjustment = MAXFLOAT;
    CGFloat horizontalCenter = proposedContentOffset.x + (CGRectGetWidth(self.collectionView.bounds) / 2.0);
    
    CGRect targetRect = CGRectMake(proposedContentOffset.x, 
                                                        0.0, 
                                                        self.collectionView.bounds.size.width, 
                                                        self.collectionView.bounds.size.height);
    
    NSArray* array = [self layoutAttributesForElementsInRect:targetRect];
    
    for (UICollectionViewLayoutAttributes* layoutAttributes in array) {
        if (layoutAttributes.representedElementCategory != UICollectionElementCategoryCell)
            continue;
    
        CGFloat itemHorizontalCenter = layoutAttributes.center.x;
        offsetAdjustment = itemHorizontalCenter - horizontalCenter;
        layoutAttributes.alpha = 0;
        
        if (velocity.x < 0) break;
    }
    
    return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}

また、ページングの動作に近くするため、UICollectionViewクラスでスクロールの速度を速くします。

/*HogeCollectionViewController.m*/
//viewDidLoadなどで...
self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast;

以上です。

※参考
http://stackoverflow.com/questions/13492037/targetcontentoffsetforproposedcontentoffsetwithscrollingvelocity-without-subcla