Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6693887
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T06:02:17+00:00 2026-05-26T06:02:17+00:00

In short, I need to know exactly when the scrollview stopped scrolling. By ‘stopped

  • 0

In short, I need to know exactly when the scrollview stopped scrolling. By ‘stopped scrolling’, I mean the moment at which it is no longer moving and not being touched.

I’ve been working on a horizontal UIScrollView subclass (for iOS 4) with selection tabs in it. One of its requirements is that it stops scrolling below a certain speed to allow user interaction more quickly. It should also snap to the start of a tab. In other words, when the user releases the scrollview and its speed is low, it snaps to a position. I’ve implemented this and it works, but there’s a bug in it.

What I have now:

The scrollview is its own delegate. at every call to scrollViewDidScroll:, it refreshes its speed-related variables:

-(void)refreshCurrentSpeed
{
    float currentOffset = self.contentOffset.x;
    NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];

    deltaOffset = (currentOffset - prevOffset);
    deltaTime = (currentTime - prevTime);    
    currentSpeed = deltaOffset/deltaTime;
    prevOffset = currentOffset;
    prevTime = currentTime;

    NSLog(@"deltaOffset is now %f, deltaTime is now %f and speed is %f",deltaOffset,deltaTime,currentSpeed);
}

Then proceeds to snap if needed:

-(void)snapIfNeeded
{
    if(canStopScrolling && currentSpeed <70.0f && currentSpeed>-70.0f)
    {
        NSLog(@"Stopping with a speed of %f points per second", currentSpeed);
        [self stopMoving];

        float scrollDistancePastTabStart = fmodf(self.contentOffset.x, (self.frame.size.width/3));
        float scrollSnapX = self.contentOffset.x - scrollDistancePastTabStart;
        if(scrollDistancePastTabStart > self.frame.size.width/6)
        {
            scrollSnapX += self.frame.size.width/3;
        }
        float maxSnapX = self.contentSize.width-self.frame.size.width;
        if(scrollSnapX>maxSnapX)
        {
            scrollSnapX = maxSnapX;
        }
        [UIView animateWithDuration:0.3
                         animations:^{self.contentOffset=CGPointMake(scrollSnapX, self.contentOffset.y);}
                         completion:^(BOOL finished){[self stopMoving];}
        ];
    }
    else
    {
        NSLog(@"Did not stop with a speed of %f points per second", currentSpeed);
    }
}

-(void)stopMoving
{
    if(self.dragging)
    {
        [self setContentOffset:CGPointMake(self.contentOffset.x, self.contentOffset.y) animated:NO];
    }
    canStopScrolling = NO;
}

Here are the delegate methods:

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    canStopScrolling = NO;
    [self refreshCurrentSpeed];
}

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    canStopScrolling = YES;
    NSLog(@"Did end dragging");
    [self snapIfNeeded];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    [self refreshCurrentSpeed];
    [self snapIfNeeded];
}

This works well most of the time, except in two scenarios:
1. When the user scrolls without releasing his/her finger and lets go at a near stationary timing right after moving, it often snaps to its position as it’s supposed to, but a lot of times, does not. It usually takes a few attempts to get it to happen. Odd values for time (very low) and/or distance (rather high) appear at the release, causing a high speed value while the scrollView is, in reality, nearly or entirely stationary.
2. When the user taps the scrollview to stop its movement, it seems the scrollview sets the contentOffset to its previous spot. This teleportation results in a very high speed value. This could be fixed by checking if the previous delta is currentDelta*-1, but I’d prefer a more stable solution.

I’ve tried using didEndDecelerating, but when the glitch occurs, it does not get called. This probably confirms that it’s stationary already. There seems to be no delegate method that gets called when the scrollview stopped moving completely.

If you’d like to see the glitch yourself, here’s some code to fill the scrollview with tabs:

@interface  UIScrollView <UIScrollViewDelegate>
{
    bool canStopScrolling;
    float prevOffset;
    float deltaOffset; //remembered for debug purposes
    NSTimeInterval prevTime;
    NSTimeInterval deltaTime; //remembered for debug purposes
    float currentSpeed;
}

-(void)stopMoving;
-(void)snapIfNeeded;
-(void)refreshCurrentSpeed;

@end


@implementation TabScrollView

-(id) init
{
    self = [super init];
    if(self)
    {
        self.delegate = self;
        self.frame = CGRectMake(0.0f,0.0f,320.0f,40.0f);
        self.backgroundColor = [UIColor grayColor];
        float tabWidth = self.frame.size.width/3;
        self.contentSize = CGSizeMake(100*tabWidth, 40.0f);
        for(int i=0; i<100;i++)
        {
            UIView *view = [[UIView alloc] init];
            view.frame = CGRectMake(i*tabWidth,0.0f,tabWidth,40.0f);
            view.backgroundColor = [UIColor colorWithWhite:(float)(i%2) alpha:1.0f];
            [self addSubview:view];
        }
    }
    return self;
}

@end

A shorter version of this question: how to know when the scrollview stopped scrolling? didEndDecelerating: does not get called when you release it stationary, didEndDragging: happens a lot during the scrolling and checking for speed is unreliable due to this odd ‘jump’ which sets the speed to something random.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T06:02:17+00:00Added an answer on May 26, 2026 at 6:02 am

    I found a solution:

    -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    

    I did not notice that last bit before, willDecelerate. It is false when the scrollView is stationary when ending the touch. Combined with the above-mentioned speed check, I can snap both when it’s slow (and not being touched) or when it’s stationary.

    For anyone not doing any snapping but needs to know when scrolling stopped, didEndDecelerating will be called at the end of the scroll movement. Combined with a check on willDecelerate in didEndDragging, you’ll know when the scrolling has stopped.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

So I have an app which plays many short sound clips. I need to
How can i shorter below codes than before? i need short and simple method:
I need a short code snippet to get a directory listing from an HTTP
I have an array of shorts (short[]) that I need to write out to
Why is there a need to convert a value (for example short) to string,
Long story short, client's hosting is using php 5.2.5 and i desperately need to
I need to sort on a date-field type, which name is mod_date. It works
I'm not exactly sure how to phrase this, but here goes... We have a
Short Version of the question: I will put a quad. I know the width
I need help being pointed in the right direction (to the right documentation or

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.