UICollectionView with CustomFlowLayout How to restrict scrolling of only one page per scroll?

I implemented customFlowLayoutin my iOS application. And I have subclassed targetContentOffsetForProposedContentOffset:withScrollingVelocityusing subclassification UICollectionViewFlowLayout. Now my problem is when the user scrolls collectionview, he should scroll only the next index. Now it scrolls randomly.
Thus, anyone has an idea that I can make the scroll restriction to only one scroll item.
The following is my code.

#pragma mark - UICollectionViewLayout (UISubclassingHooks)

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
  CGSize collectionViewSize = self.collectionView.bounds.size;
  CGFloat proposedContentOffsetCenterX = proposedContentOffset.x + collectionViewSize.width / 2;
  CGRect proposedRect = CGRectMake(proposedContentOffset.x, 0, collectionViewSize.width, collectionViewSize.height);
  UICollectionViewLayoutAttributes *candidateAttributes;
  for (UICollectionViewLayoutAttributes *attributes in [self layoutAttributesForElementsInRect:proposedRect]) {
    if (attributes.representedElementCategory != UICollectionElementCategoryCell) continue;
    if (!candidateAttributes) {
      candidateAttributes = attributes;
      continue;
    }
    if (fabs(attributes.center.x - proposedContentOffsetCenterX) < fabs(candidateAttributes.center.x - proposedContentOffsetCenterX)) {
      candidateAttributes = attributes;
    }
  }

  proposedContentOffset.x = candidateAttributes.center.x - self.collectionView.bounds.size.width / 2;

  CGFloat offset = proposedContentOffset.x - self.collectionView.contentOffset.x;

  if ((velocity.x < 0 && offset > 0) || (velocity.x > 0 && offset < 0)) {
    CGFloat pageWidth = self.itemSize.width + self.minimumLineSpacing;
    proposedContentOffset.x += velocity.x > 0 ? pageWidth : -pageWidth;
  }

  return proposedContentOffset;
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
  return YES;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
  if (!self.scaleItems) return [super layoutAttributesForElementsInRect:rect];

  NSArray *attributesArray = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];

  CGRect visibleRect = (CGRect){self.collectionView.contentOffset, self.collectionView.bounds.size};
  CGFloat visibleCenterX = CGRectGetMidX(visibleRect);

  [attributesArray enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *attributes, NSUInteger idx, BOOL *stop) {
    CGFloat distanceFromCenter = visibleCenterX - attributes.center.x;
    CGFloat absDistanceFromCenter = MIN(ABS(distanceFromCenter), self.scalingOffset);
    CGFloat scale = absDistanceFromCenter * (self.minimumScaleFactor - 1) / self.scalingOffset + 1;
    attributes.transform3D = CATransform3DScale(CATransform3DIdentity, scale, scale, 1);
  }];

  return attributesArray;
}
+4
source share
1 answer

, . , , , , . , , .

, , , ...

, , , proposedContentOffset ( ).

, , ( , ). + - .

. , - :

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
    CGSize collectionViewSize = self.collectionView.bounds.size;
    CGFloat width = collectionViewSize.width;
    CGFloat halfWidth = width * 0.5;

    CGFloat direction = (proposedContentOffset.x > self.collectionView.contentOffset.x ? 1 : 0);
    CGFloat pageOffsetX = 250.0 * floor(self.collectionView.contentOffset.x / 250.0); 
    CGFloat proposedContentOffsetCenterX = pageOffsetX + (width * direction);
    CGRect proposedRect = CGRectMake(proposedContentOffsetCenterX, 0, collectionViewSize.width, collectionViewSize.height);

    UICollectionViewLayoutAttributes *candidateAttributes;

    for (UICollectionViewLayoutAttributes *attributes in [self layoutAttributesForElementsInRect:proposedRect]) {
        if (attributes.representedElementCategory != UICollectionElementCategoryCell) continue;

        candidateAttributes = attributes;
        break;
    }

    proposedContentOffset.x = candidateAttributes.center.x - halfWidth;

//     CGFloat offset = proposedContentOffset.x - self.collectionView.contentOffset.x;
//     
//     if ((velocity.x < 0 && offset > 0) || (velocity.x > 0 && offset < 0)) {
//         CGFloat pageWidth = self.itemSize.width + self.minimumLineSpacing;
//         proposedContentOffset.x += velocity.x > 0 ? pageWidth : -pageWidth;
//     }

    return proposedContentOffset;
}

, . , , .

+1

All Articles