使用scrollViewWillEndDragging自定义UIScrollView分页

时间:2012-02-20 19:58:59

标签: ios uiscrollview uikit uiscrollviewdelegate

我正在尝试使用新的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; 
}

5 个答案:

答案 0 :(得分:50)

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

- (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以正确的方式指出。

答案 1 :(得分:9)

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
}

答案 2 :(得分:6)

我能够进行快速测试并使其正确点火并使我的物体按需要停止。我使用以下简单测试做到了这一点:

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

似乎这种方法可能不是您的代码中的问题,但更有可能的是,'goodOffsetX'无法正确计算要停止的有效值。

答案 3 :(得分:3)

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

我还使用@skagedal建议的collectionView?.decelerationRate = UIScrollViewDecelerationRateFast来提高网页速度。

答案 4 :(得分:-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
 }