UICollectionView 按照 Cell 宽度分页

效果展示

分析

如果直接打开系统的pagingEnabled分页, 它只会根据Cell的Bounds分页。如果cell不是屏幕宽度的话,就不能使用了,需要我们对滚动进行计算了。

方案一

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
*targetContentOffset = scrollView.contentOffset; // set acceleration to 0.0
float pageWidth = (float)self.articlesCollectionView.bounds.size.width;
int minSpace = 10;
int cellToSwipe = (scrollView.contentOffset.x)/(pageWidth + minSpace) + 0.5; // cell width + min spacing for lines
if (cellToSwipe < 0) {
cellToSwipe = 0;
} else if (cellToSwipe >= self.articles.count) {
cellToSwipe = self.articles.count - 1;
}
[self.articlesCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:cellToSwipe inSection:0] atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}

在手指松开的时候,开始计算滚动的下一个位置。这个方法虽然也可以实现需求,但是效果比较生硬,不是很推荐。

具体可以看 :查看其中的「分页的几种实现方式」

方案二

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)offset
withScrollingVelocity:(CGPoint)velocity {
CGRect cvBounds = self.collectionView.bounds;
CGFloat halfWidth = cvBounds.size.width * 0.5f;
CGFloat proposedContentOffsetCenterX = offset.x + halfWidth;
NSArray* attributesArray = [self layoutAttributesForElementsInRect:cvBounds];
UICollectionViewLayoutAttributes* candidateAttributes;
for (UICollectionViewLayoutAttributes* attributes in attributesArray) {
// == Skip comparison with non-cell items (headers and footers) == //
if (attributes.representedElementCategory !=
UICollectionElementCategoryCell) {
continue;
}
// == First time in the loop == //
if(!candidateAttributes) {
candidateAttributes = attributes;
continue;
}
if (fabs(attributes.center.x - proposedContentOffsetCenterX) <
fabs(candidateAttributes.center.x - proposedContentOffsetCenterX)) {
candidateAttributes = attributes;
}
}
return CGPointMake(candidateAttributes.center.x - halfWidth, offset.y);
}

通过重写UICollectionViewLayout的方法,根据计算返回最终的悬停位置。

目前还存在的问题

滑动如果比较慢的话,它跳转到下一页的也会比较慢。

可以通过设置 decelerationRate 的值,来决定手指放开后的减速率,范围为0-1。然而经过测试,发现是可以加速,但是会出现莫名的卡顿。

2017年3月10号更新

使用UIScrollview 按照view宽度分页的方法:
详见DEMO: https://github.com/labmain/UIScrollViewCellWidthPage

解决了 UICollectionView 滑动比较慢的问题。

Demo 地址

github