2012-02-20 123 views
19

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

有没有人能够正确使用它,并使其工作?是否还有其他必须实施的代表呼叫才能使其工作?

这里是我万一有人看到代码什么毛病吧:

- (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; 
} 
+2

演示你有'pagingEnabled'设置为'YES'这个滚动视图? – 2012-02-20 20:36:17

+3

pagingEnabled设置为NO,文档说它需要设置为NO才能调用该代理。我也尝试将它设置为YES仅用于踢腿,并且不会按照文档调用,但有一些控制台日志记录表示不会将pagingEnabled设置为YES。 – Alex 2012-02-20 20:47:41

+0

我的问题是我在运行iOS4的手机上测试它。 另外,你有没有设置UIScrollView的委托属性? – Marc 2012-04-04 12:40:59

回答

49

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

- (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指向正确的方向。

+6

这是我迄今为止发现的模拟默认实现的最佳解决方案(一次只滚动一个页面,处理缓慢的拖动等) – 2013-08-26 20:20:56

+2

这可以工作,但如果拖动速度太小,拖动结束将向新页面移动得太慢。有关如何解决这个问题的任何建议? – skagedal 2015-11-08 09:02:39

+13

要回答我自己的问题,请设置self.scrollView.decelerationRate = UIScrollViewDecelerationRateFast,事情会很好! :) – skagedal 2015-11-08 11:14:07

7

我能够运行一个快速测试,并得到这个正确火,让我的对象停止根据需要。我这样做是使用以下简单的测试:

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

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

3

雨燕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 = UIScrollViewDecelerationRateFast通过@skagedal的建议,以提高速度。

6

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 
} 
+0

值得注意的是,如果您有顶部或左侧插图,则需要在分配之前将其添加到点值。 – Sethmr 2017-09-27 16:30:16

-1
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 
}