iOS - collectionView contentOffset 中的 CGPoint 值不准确
iOS - inaccurate CGPoint value in collectionView contentOffset
我已经创建了这个包含 13 个图标的无限 collectionView 循环,但是它在 320 x 568 分辨率的设备上无法正常工作。问题在于滚动时计算适当的图像 contentOffset(这是一个动画 - 它不可触摸)并且一段时间后它不居中。这些图像之间的间距相等,因为我想一次在屏幕上显示 3 个图标。当 3 个图标通过 previousContentOffset 时,x = 319.5 应该是 x = 320.0 对于这种特殊情况,有什么解决方法的建议吗?也许通过单个图标迭代?我在 1 个图标幻灯片后得到的结果:
previousContentOffset = (CGPoint)(x = 106.5, y = 0),
宽度=(双)106.66666666666667,
currentContentOffset = (CGPoint)(x = 213.16666666666669, y = 0)
// 无限循环
- (void)setupDataForCollectionView {
NSArray *originalArray = self.arrayImages;
NSMutableArray *workingArray = [originalArray mutableCopy];
self.dataArray = [workingArray mutableCopy];
}
// Implementation of infinite loop
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// calculate width for every device
double contentOffsetWhenFullyScrolledRight = self.collectionViewHorizontal.contentSize.width - self.collectionViewHorizontal.frame.size.width;
if (scrollView.contentOffset.x == contentOffsetWhenFullyScrolledRight) {
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:1 inSection:0];
[self.collectionViewHorizontal scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
} else if (scrollView.contentOffset.x == 0) {
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:([self.dataArray count] -2) inSection:0];
[self.collectionViewHorizontal scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
}
}
// TimeInterval for animation
- (void)timerAction:(NSTimer *)timer {
//previous icon content offset
CGPoint previousContentOffSet = self.collectionViewHorizontal.contentOffset;
//next icon width
double width = self.collectionViewHorizontal.frame.size.width / 3;
// NSUInteger index = (int)(floor(self.collectionViewHorizontal.contentOffset.x / width) + 1);
// animate icons scroll view
CGPoint currentContentOffset = CGPointMake(previousContentOffSet.x + width, previousContentOffSet.y);
NSIndexPath *indexPath = [self.collectionViewHorizontal indexPathForItemAtPoint:currentContentOffset];
if (indexPath.row > self.dataArray.count - 4) {
// add elements and reload
[self.dataArray addObjectsFromArray:[self.arrayImages copy]];
[self.collectionViewHorizontal reloadData];
}
// sliding animation
[UIView animateWithDuration:.3 delay:.0 usingSpringWithDamping:0.5 initialSpringVelocity:.0 options:kNilOptions animations:^{
self.collectionViewHorizontal.contentOffset = currentContentOffset;
} completion:^(BOOL finished) {
[self scrollViewDidEndDecelerating:self.collectionViewHorizontal];
}];
}
我不久前实施了一个解决方法,所以我想我应该分享一下。我决定使用当前图标的索引而不是 contentOffset 进行迭代。
我创建了一个 NSInteger 属性 currentIndex 并添加了计时器方法。
- (void)timerAction:(NSTimer *)timer {
self.currentIndex++;
//next icon width
double width = self.collectionViewHorizontal.frame.size.width / 3;
// animate icons scroll view
CGPoint currentContentOffset = CGPointMake(self.currentIndex * width, 0.0);
NSIndexPath *indexPath = [self.collectionViewHorizontal indexPathForItemAtPoint:currentContentOffset];
if (indexPath.row > (self.dataArray.count /2) {
// add elements and reload
[self.dataArray addObjectsFromArray:[self.arrayImages copy]];
[self.collectionViewHorizontal reloadData];
}
// sliding animation
[UIView animateWithDuration:.3 delay:.0 usingSpringWithDamping:0.5 initialSpringVelocity:.0 options:kNilOptions animations:^{
self.collectionViewHorizontal.contentOffset = currentContentOffset;
} completion:^(BOOL finished) {
[self scrollViewDidEndDecelerating:self.collectionViewHorizontal];
}];
}
我已经创建了这个包含 13 个图标的无限 collectionView 循环,但是它在 320 x 568 分辨率的设备上无法正常工作。问题在于滚动时计算适当的图像 contentOffset(这是一个动画 - 它不可触摸)并且一段时间后它不居中。这些图像之间的间距相等,因为我想一次在屏幕上显示 3 个图标。当 3 个图标通过 previousContentOffset 时,x = 319.5 应该是 x = 320.0 对于这种特殊情况,有什么解决方法的建议吗?也许通过单个图标迭代?我在 1 个图标幻灯片后得到的结果:
previousContentOffset = (CGPoint)(x = 106.5, y = 0),
宽度=(双)106.66666666666667,
currentContentOffset = (CGPoint)(x = 213.16666666666669, y = 0)
// 无限循环
- (void)setupDataForCollectionView {
NSArray *originalArray = self.arrayImages;
NSMutableArray *workingArray = [originalArray mutableCopy];
self.dataArray = [workingArray mutableCopy];
}
// Implementation of infinite loop
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// calculate width for every device
double contentOffsetWhenFullyScrolledRight = self.collectionViewHorizontal.contentSize.width - self.collectionViewHorizontal.frame.size.width;
if (scrollView.contentOffset.x == contentOffsetWhenFullyScrolledRight) {
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:1 inSection:0];
[self.collectionViewHorizontal scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
} else if (scrollView.contentOffset.x == 0) {
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:([self.dataArray count] -2) inSection:0];
[self.collectionViewHorizontal scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
}
}
// TimeInterval for animation
- (void)timerAction:(NSTimer *)timer {
//previous icon content offset
CGPoint previousContentOffSet = self.collectionViewHorizontal.contentOffset;
//next icon width
double width = self.collectionViewHorizontal.frame.size.width / 3;
// NSUInteger index = (int)(floor(self.collectionViewHorizontal.contentOffset.x / width) + 1);
// animate icons scroll view
CGPoint currentContentOffset = CGPointMake(previousContentOffSet.x + width, previousContentOffSet.y);
NSIndexPath *indexPath = [self.collectionViewHorizontal indexPathForItemAtPoint:currentContentOffset];
if (indexPath.row > self.dataArray.count - 4) {
// add elements and reload
[self.dataArray addObjectsFromArray:[self.arrayImages copy]];
[self.collectionViewHorizontal reloadData];
}
// sliding animation
[UIView animateWithDuration:.3 delay:.0 usingSpringWithDamping:0.5 initialSpringVelocity:.0 options:kNilOptions animations:^{
self.collectionViewHorizontal.contentOffset = currentContentOffset;
} completion:^(BOOL finished) {
[self scrollViewDidEndDecelerating:self.collectionViewHorizontal];
}];
}
我不久前实施了一个解决方法,所以我想我应该分享一下。我决定使用当前图标的索引而不是 contentOffset 进行迭代。 我创建了一个 NSInteger 属性 currentIndex 并添加了计时器方法。
- (void)timerAction:(NSTimer *)timer {
self.currentIndex++;
//next icon width
double width = self.collectionViewHorizontal.frame.size.width / 3;
// animate icons scroll view
CGPoint currentContentOffset = CGPointMake(self.currentIndex * width, 0.0);
NSIndexPath *indexPath = [self.collectionViewHorizontal indexPathForItemAtPoint:currentContentOffset];
if (indexPath.row > (self.dataArray.count /2) {
// add elements and reload
[self.dataArray addObjectsFromArray:[self.arrayImages copy]];
[self.collectionViewHorizontal reloadData];
}
// sliding animation
[UIView animateWithDuration:.3 delay:.0 usingSpringWithDamping:0.5 initialSpringVelocity:.0 options:kNilOptions animations:^{
self.collectionViewHorizontal.contentOffset = currentContentOffset;
} completion:^(BOOL finished) {
[self scrollViewDidEndDecelerating:self.collectionViewHorizontal];
}];
}