具有分页功能的UIScrollView的灵敏度/滚动速度

UrK*_*UrK 27 uiscrollview ios

我希望UIScrollView在快速扫描后快速滚动,就像这样.虽然,当打开分页时,滚动一次只能处理一页.是否可以快速滚动,只需轻轻一按手指启用分页而无需使用手势识别器手动实现?

sim*_*eon 53

这是相当简单的,但是您必须自己实现分页方面(这非常简单).您不需要手势识别器.

迅速

首先,调整您的UIScrollView减速率:

scrollView.decelerationRate = UIScrollViewDecelerationRateFast
Run Code Online (Sandbox Code Playgroud)

假设我们有一系列内容 - 让我们称之为yourPagesArray.在UIScrollViewDelegate中,实现以下方法:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
{
    //This is the index of the "page" that we will be landing at
    let nearestIndex = Int(CGFloat(targetContentOffset.pointee.x) / scrollView.bounds.size.width + 0.5)

    //Just to make sure we don't scroll past your content
    let clampedIndex = max( min( nearestIndex, yourPagesArray.count - 1 ), 0 )

    //This is the actual x position in the scroll view
    var xOffset = CGFloat(clampedIndex) * scrollView.bounds.size.width

    //I've found that scroll views will "stick" unless this is done
    xOffset = xOffset == 0.0 ? 1.0 : xOffset

    //Tell the scroll view to land on our page
    targetContentOffset.pointee.x = xOffset
}
Run Code Online (Sandbox Code Playgroud)

您还需要实现以下委托方法,以处理用户轻轻抬起手指而不会导致任何滚动减速的情况:

(更新:您可能不需要在最新的iOS SDK下执行此操作.现在,当速度为零时,会调用上面的委托方法.)

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
{
    if !decelerate
    {
        let currentIndex = floor(scrollView.contentOffset.x / scrollView.bounds.size.width)

        let offset = CGPoint(x: scrollView.bounds.size.width * currentIndex, y: 0)

        scrollView.setContentOffset(offset, animated: true)
    }
}
Run Code Online (Sandbox Code Playgroud)

Objective-C的

设置减速率:

scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
Run Code Online (Sandbox Code Playgroud)

然后你的滚动视图委托实现:

- (void) scrollViewWillEndDragging:(UIScrollView *)scroll withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    //This is the index of the "page" that we will be landing at
    NSUInteger nearestIndex = (NSUInteger)(targetContentOffset->x / scrollView.bounds.size.width + 0.5f);   

    //Just to make sure we don't scroll past your content
    nearestIndex = MAX( MIN( nearestIndex, yourPagesArray.count - 1 ), 0 );

    //This is the actual x position in the scroll view
    CGFloat xOffset = nearestIndex * scrollView.bounds.size.width;

    //I've found that scroll views will "stick" unless this is done
    xOffset = xOffset==0?1:xOffset;

    //Tell the scroll view to land on our page
    *targetContentOffset = CGPointMake(xOffset, targetContentOffset->y);
}

- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if( !decelerate )
    {
        NSUInteger currentIndex = (NSUInteger)(scrollView.contentOffset.x / scrollView.bounds.size.width);

        [scrollView setContentOffset:CGPointMake(scrollView.bounds.size.width * currentIndex, 0) animated:YES];
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 每当速度指向与当前位置的新 contentOffset 相反的方向时,这仍然会导致抖动行为。 (2认同)