使用scrollViewWillEndDragging自定义UIScrollView分页

我试图使用新的scrollViewWillEndDragging:withVelocity:targetContentOffset:在iOS 5的UIScrollView委托调用,但我似乎无法得到它实际回应我正确。 我正在改变targetContentOffset-> x值,但它永远不会被使用。 我知道代码正在运行,因为它会打到该函数的断点。 我甚至尝试将偏移值设置为一个硬编码的数字,所以我会知道它会在哪里结束,但它永远不会工作。

有没有人能够正确使用它,并使其工作? 有没有其他的代表电话必须执行才能使其工作?

这是我的代码,以防有人看到有什么问题:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { // goodOffsetX returns the contentOffset i want the scrollView to stop at CGFloat goodOffsetX = [self _horizontalContentOffsetForTargetHorizontalContentOffset:(*targetContentOffset).x velocity:velocity.x]; NSLog( @" " ); NSLog( @"scrollViewWillEndDragging" ); NSLog( @" velocity: %f", velocity.x ); NSLog( @" currentX: %f", scrollView.contentOffset.x ); NSLog( @" uikit targetX: %f", (*targetContentOffset).x ); NSLog( @" pagedX: %f", goodOffsetX ); targetContentOffset->x = goodOffsetX; } 

您可以使用以下代码实现自定义分页:

 - (float) pageWidth { return ((UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout).itemSize.width + ((UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout).minimumInteritemSpacing; } - (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView { CGFloat pageWidth = self.collectionView.frame.size.width + 10 /* Optional Photo app like gap between images. Or use [self pageWidth] in case if you want the next page be also visible */; _currentPage = floor((self.collectionView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; NSLog(@"Dragging - You are now on page %i", _currentPage); } - (void) scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint*)targetContentOffset { CGFloat pageWidth = self.collectionView.frame.size.width + 10; // [self pageWidth] int newPage = _currentPage; if (velocity.x == 0) { // slow dragging not lifting finger newPage = floor((targetContentOffset->x - pageWidth / 2) / pageWidth) + 1; } else { newPage = velocity.x > 0 ? _currentPage + 1 : _currentPage - 1; if (newPage < 0) newPage = 0; if (newPage > self.collectionView.contentSize.width / pageWidth) newPage = ceil(self.collectionView.contentSize.width / pageWidth) - 1.0; } NSLog(@"Dragging - You will be on %i page (from page %i)", newPage, _currentPage); *targetContentOffset = CGPointMake(newPage * pageWidth, targetContentOffset->y); } 

当然,你必须设置pagingEnabled = NO。 _currentPage是一个类iVar。 感谢http://www.mysamplecode.com/2012/12/ios-scrollview-example-with-paging.html指出正确的方式&#x3002;

我能够运行一个快速testing,并得到这个正确的火,使我的对象停止按需。 我使用以下简单的testing来做到这一点:

 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { targetContentOffset->x = scrollView.contentOffset.x - 10; } 

看来这种方法可能不是你的代码中的问题,但更有可能的是,你的'goodOffsetX'没有正确计算一个有效的值停止在。

SWIFT 3

在这里演示一下https://github.com/damienromito/CollectionViewCustom

 func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { let pageWidth = Float(itemWidth + itemSpacing) let targetXContentOffset = Float(targetContentOffset.pointee.x) let contentWidth = Float(collectionView!.contentSize.width ) var newPage = Float(self.pageControl.currentPage) if velocity.x == 0 { newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0 } else { newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1) if newPage < 0 { newPage = 0 } if (newPage > contentWidth / pageWidth) { newPage = ceil(contentWidth / pageWidth) - 1.0 } } let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y) targetContentOffset.pointee = point } 

Swift 2.2:

 extension SomeCollectionViewController { override func scrollViewWillBeginDragging(scrollView: UIScrollView) { let pageWidth = Float(collectionView!.frame.size.width) let xCurrentOffset = Float(collectionView!.contentOffset.x) currentPage = floor((xCurrentOffset - pageWidth / 2) / pageWidth) + 1 } override func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { let pageWidth = Float(collectionView!.frame.size.width) let targetXContentOffset = Float(targetContentOffset.memory.x) let contentWidth = Float(collectionView!.contentSize.width) var newPage = currentPage if velocity.x == 0 { newPage = floor((targetXContentOffset - pageWidth / 2) / pageWidth) + 1 } else { newPage = velocity.x > 0 ? currentPage + 1 : currentPage - 1 if newPage < 0 { newPage = 0 } if newPage > contentWidth / pageWidth { newPage = ceil(contentWidth / pageWidth) - 1.0 } } targetContentOffset.memory.x = CGFloat(newPage * pageWidth) } } 

我还使用collectionView?.decelerationRate = UIScrollViewDecelerationRateFastbuild议的collectionView?.decelerationRate = UIScrollViewDecelerationRateFast来提高页面速度。

 public func scrollViewWillEndDragging(_ scrollView: UIScrollView ,withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>){ let pageWidth = Float(appWidth + itemSpacing) let targetXContentOffset = Float(targetContentOffset.pointee.x) var newPage = Float(currentPageIndex) // I use this way calculate newPage: newPage = roundf(targetXContentOffset / pageWidth); //if velocity.x == 0 { // newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0 //} else { // newPage = Float(velocity.x > 0 ? newPage + 1 : newPage - 1) // if newPage < 0 { // newPage = 0 // } // if (newPage > contentWidth / pageWidth) { // newPage = ceil(contentWidth / pageWidth) - 1.0 // } //} let targetOffsetX = CGFloat(newPage * pageWidth) let point = CGPoint (x: targetOffsetX, y: targetContentOffset.pointee.y) targetContentOffset.pointee = point }