I'm using the code from the Apple demo in a subclass of UICollectionViewFlowLayout
:
- (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);
}
This works in the sense that whenever I swipe / pan and release, an item will snap into place. But the proposed content offset is proportional to the swipe velocity. What I'm trying to do is that, no matter how fast / slow I swipe, the collection view only snaps to the next item immediately before or after the one that's currently centered.
I tried doing this:
- (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);
}
But it's not quite right. Sometimes it'll skip an item and snap to the next one after that (that is, it'll not snap to the item immediately next to the one I start scrolling from, but the one next to the one immediately next).
Any thoughts?
Ok so I figured how to make it work by making everything relative to the current 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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With