无论滚动速度如何,如何在每次滑动时将集合视图项捕捉到一个
Posted
技术标签:
【中文标题】无论滚动速度如何,如何在每次滑动时将集合视图项捕捉到一个【英文标题】:how to snap collection view items to one per swipe regardless of scrolling velocity 【发布时间】:2013-12-05 22:29:07 【问题描述】:我在 UICollectionViewFlowLayout
的子类中使用 Apple 演示中的代码:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
CGFloat offsetAdjustment = MAXFLOAT;
CGFloat horizontalCenter = proposedContentOffset.x + self.collectionView.bounds.size.width / 2.;
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0., self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
UICollectionViewLayoutAttributes *targetAttributes = nil;
NSArray *attributes = [super layoutAttributesForElementsInRect:targetRect];
for (UICollectionViewLayoutAttributes *a in attributes)
CGFloat itemHorizontalCenter = a.center.x;
if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment))
offsetAdjustment = itemHorizontalCenter - horizontalCenter;
targetAttributes = a;
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
这在某种意义上是有效的,每当我滑动/平移并释放时,一个项目就会卡入到位。但建议的内容偏移量与滑动速度成正比。我想要做的是,无论我滑动多快/多慢,集合视图只会捕捉到当前居中的项目之前或之后的下一个项目。
我试过这样做:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
NSInteger currentPage = (int)(self.collectionView.contentOffset.x / self.collectionView.bounds.size.width);
if (proposedContentOffset.x > self.collectionView.contentOffset.x)
currentPage = (MIN(currentPage + 1, ((int)(self.collectionView.contentSize.width / self.collectionView.bounds.size.width)) - 1));
proposedContentOffset.x = self.collectionView.bounds.size.width * currentPage;
CGFloat offsetAdjustment = MAXFLOAT;
CGFloat horizontalCenter = proposedContentOffset.x + self.collectionView.bounds.size.width / 2.;
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0., self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
UICollectionViewLayoutAttributes *targetAttributes = nil;
NSArray *attributes = [super layoutAttributesForElementsInRect:targetRect];
for (UICollectionViewLayoutAttributes *a in attributes)
CGFloat itemHorizontalCenter = a.center.x;
if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment))
offsetAdjustment = itemHorizontalCenter - horizontalCenter;
targetAttributes = a;
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
但这并不完全正确。有时它会跳过一个项目并在此之后捕捉到下一个项目(也就是说,它不会捕捉到紧挨我开始滚动的项目旁边的项目,而是紧邻下一个项目的项目)。
有什么想法吗?
【问题讨论】:
【参考方案1】:好的,所以我想出了如何通过使所有内容都与当前的 contentOffset
相关来使其工作:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
if (proposedContentOffset.x > self.collectionView.contentOffset.x)
proposedContentOffset.x = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width / 2.;
else if (proposedContentOffset.x < self.collectionView.contentOffset.x)
proposedContentOffset.x = self.collectionView.contentOffset.x - self.collectionView.bounds.size.width / 2.;
CGFloat offsetAdjustment = MAXFLOAT;
CGFloat horizontalCenter = proposedContentOffset.x + self.collectionView.bounds.size.width / 2.;
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0., self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray *attributes = [super layoutAttributesForElementsInRect:targetRect];
for (UICollectionViewLayoutAttributes *a in attributes)
CGFloat itemHorizontalCenter = a.center.x;
if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment))
offsetAdjustment = itemHorizontalCenter - horizontalCenter;
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
【讨论】:
您的代码运行良好。我们可以让它一次只滚动一个页面吗?目前,就我而言,如果我滚动得太快,它将跳过多个页面。这是我的question。以上是关于无论滚动速度如何,如何在每次滑动时将集合视图项捕捉到一个的主要内容,如果未能解决你的问题,请参考以下文章
Swift UIScrollView 在没有 pagingEnabled 的情况下捕捉到子视图宽度