UICollectionView与CustomFlowLayout如何限制每滚动只有一个页面滚动?
我在我的iOS应用程序中实现了customFlowLayout
。 我已经通过子类化UICollectionViewFlowLayout
子类化了targetContentOffsetForProposedContentOffset:withScrollingVelocity
UICollectionViewFlowLayout
。 现在我的问题是当用户滚动collectionview
它必须滚动到只有下一个索引。 现在它随机滚动。
所以任何人都有任何想法,我怎样才能使滚动限制只有一个项目每卷。
以下是我的代码。
#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; }
您的代码看起来应该根据用户请求很好地滚动。 即如果他们快速滚动,它将跳过一些项目,很好地落在后面的项目,如果他们慢慢滚动,将进行到下一个或返回到前一个项目很好地根据滚动距离。 但是,这不是你说的你想要的。
当用户试图快速滚动时,您想要的内容可能不太好
无论如何,要得到你想要的,你基本上只想使用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; }
我已经注意到底部的部分,因为它不应该是最初版本所必需的。 先用一个简单的版本进行testing,然后详细说明是否需要在边缘情况下进行更多的控制。
- UITableView不滚动时没有分配给父母的UIViewController视图属性
- 如何在UIScrollview中embedded一个UITableView
- iOS / WebKit:touchmove / touchstart不能在input&textarea上工作
- UITableview Scroll将擦除UITableviewcell中的文本字段中的数据
- 为什么我的cordovaWebView有一个额外的20像素的滚动?
- SDWebImage在单元格中重复图像,而不是等待加载。
- iOS:uitableview将第一个单元格上的对象重绘到底部单元格
- UITableView与图像滚动很慢
- iOS UITableView单元格滚动后加载不正确?