UIScrollView 的灵敏度/滚动速度与分页

Posted

技术标签:

【中文标题】UIScrollView 的灵敏度/滚动速度与分页【英文标题】:Sensitivity/Scroll speed of UIScrollView with paging 【发布时间】:2012-07-19 13:30:49 【问题描述】:

我希望 UIScrollView 在快速扫描后快速滚动,like this。 虽然,当打开分页时,滚动工作one page at a time。 是否可以在不使用手势识别器手动实现的情况下通过手指轻弹启用分页时快速滚动?

【问题讨论】:

找到解决方案了吗? 我希望有一个好的解决方案。似乎有两种实现方式:手动实现手势识别器或手动实现分页。 是的,我可能在 6 个月前就实施了。你可以手动做手势识别器.. @JohnWhite,如果您在某处有实现,我将不胜感激。与其从头开始,不如有一些坚实的工作基础。 【参考方案1】:

这很简单,但是您必须自己实现分页方面(这很简单)。您不需要手势识别器。

斯威夫特

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

scrollView.decelerationRate = UIScrollViewDecelerationRateFast

假设我们有一个内容数组——我们称之为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

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

(更新:在最新的 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)
    

目标-C

设置你的减速率:

scrollView.decelerationRate = UIScrollViewDecelerationRateFast;

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

- (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];
    

【讨论】:

这是一个漂亮简洁的答案。谢谢!我可能会补充一点,使用缓慢的减速率可以提供更“流畅”的滚动动作,即在停止之前它会滚动更多页面。 太棒了! scrollView.decelerationRate = UIScrollViewDecelerationRateFast;是让行为更像scrollView.pagingEnabled = YES;的关键,终于弄明白了,谢谢! 当速度指向与当前位置的新内容偏移相反的方向时,这仍然会导致抖动行为。【参考方案2】:

我认为当我们的手指触摸它时,我们可以设置 scrollView.userInteractionEnabled = NO。然后当动画停止时,打开它。它对我有用。 希望对你有帮助。

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    scrollView.userInteractionEnabled = NO;


// at the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
    scrollView.userInteractionEnabled = YES;

【讨论】:

以上是关于UIScrollView 的灵敏度/滚动速度与分页的主要内容,如果未能解决你的问题,请参考以下文章

OCUI界面设计:滚动视图与分页控件初探

如何加快 UIScrollView 中的滚动速度? [关闭]

与分页相关的哪些 LINQ 操作可能会减慢我的查询速度?

如何显示IList 与分页

分页 UIScrollView 内的 UIScrollView

调整 UICollectionView 滚动速度/灵敏度