I know how to get the contentOffset on movement for a UIScrollView, can someone explain to me how I can get an actual number that represents the current speed of a UIScrollView while it is tracking, or decelerating?
-
Not a big deal but I put in the modern solution to this very old question down the bottom. – Fattie Jul 14 '17 at 10:29
8 Answers
There's an easier way: check the UISCrollview's pan gesture recognizer. With it, you can get the velocity like so:
CGPoint scrollVelocity = [[_scrollView panGestureRecognizer] velocityInView:self];

- 1,482
- 11
- 8
-
28Handy! The only downside is that `scrollVelocity` will be 0.0f immediately after the user lifts their finger (because this ends the panning gesture). So it's a good way to measure velocity while the scrollview is being dragged, but doesn't work if flicked. – Kyle Fox Apr 09 '12 at 17:33
-
2..and of course the panGestureRecognizer is only exposed in iOS 5 onwards. – bandejapaisa Aug 20 '12 at 11:00
-
is the scroll velocity a point because it records vertical and horizontal speeds? – rolling_codes Jul 30 '14 at 13:11
-
1to what @KyleFox said, yes of course true, make use of `scrollViewWillEndDragging:withVelocity:targetContentOffset:` to perhaps handle and velocity or offset conditions AFTER the current touch event ends – Will Von Ullrich Jun 01 '17 at 19:32
-
1
Have these properties on your UIScrollViewDelegate
CGPoint lastOffset;
NSTimeInterval lastOffsetCapture;
BOOL isScrollingFast;
Then have this code for your scrollViewDidScroll:
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint currentOffset = scrollView.contentOffset;
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval timeDiff = currentTime - lastOffsetCapture;
if(timeDiff > 0.1) {
CGFloat distance = currentOffset.y - lastOffset.y;
//The multiply by 10, / 1000 isn't really necessary.......
CGFloat scrollSpeedNotAbs = (distance * 10) / 1000; //in pixels per millisecond
CGFloat scrollSpeed = fabsf(scrollSpeedNotAbs);
if (scrollSpeed > 0.5) {
isScrollingFast = YES;
NSLog(@"Fast");
} else {
isScrollingFast = NO;
NSLog(@"Slow");
}
lastOffset = currentOffset;
lastOffsetCapture = currentTime;
}
}
And from this i'm getting pixels per millisecond, which if is greater than 0.5, i've logged as fast, and anything below is logged as slow.
I use this for loading some cells on a table view animated. It doesn't scroll so well if I load them when the user is scrolling fast.

- 19,551
- 4
- 71
- 68

- 26,576
- 13
- 94
- 112
-
1
-
4thanks for a nice solution, the only thing I'd change is replace 0.1 with `captureInterval` const and than use it also in calculation of `scrollSpeedNotAbs` to increase readability of the algorithm (as the brain stops on `* 10` because general formula of speed is distance / time). – zubko Oct 21 '12 at 19:20
-
2wonderful extension to the scrollview / collectionView ! Saved my day :-) – PetrV Jul 19 '13 at 12:21
-
While this is not incorrect, I put in the modern solution to this very old question down the bottom. Cheers – Fattie Jul 14 '17 at 10:29
-
@Fattie I just tried this and it seems to work fine. Why did you say that it's not correct – Lance Samaria Mar 06 '22 at 18:46
-
@LanceSamaria I said it is ***not*** incorrect, but it is very old fashioned, slow, and complicated, and does not exactly follow how it works in modern iOS. Simply use the far easier solution below. – Fattie Mar 07 '22 at 01:54
Converted @bandejapaisa answer to Swift 5:
Properties used by UIScrollViewDelegate:
var lastOffset: CGPoint = .zero
var lastOffsetCapture: TimeInterval = .zero
var isScrollingFast: Bool = false
And the scrollViewDidScroll function:
func scrollViewDidScroll(scrollView: UIScrollView) {
let currentOffset = scrollView.contentOffset
let currentTime = Date.timeIntervalSinceReferenceDate
let timeDiff = currentTime - lastOffsetCapture
let captureInterval = 0.1
if timeDiff > captureInterval {
let distance = currentOffset.y - lastOffset.y // calc distance
let scrollSpeedNotAbs = (distance * 10) / 1000 // pixels per ms*10
let scrollSpeed = fabsf(Float(scrollSpeedNotAbs)) // absolute value
if scrollSpeed > 0.5 {
isScrollingFast = true
print("Fast")
} else {
isScrollingFast = false
print("Slow")
}
lastOffset = currentOffset
lastOffsetCapture = currentTime
}
}

- 1,165
- 2
- 11
- 27
For a simple speed calculation (All the other answers are more complicated):
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scrollSpeed = scrollView.contentOffset.y - previousScrollViewYOffset;
previousTableViewYOffset = scrollView.contentOffset.y;
}

- 8,180
- 5
- 45
- 52
-
This helped me out as well, thanks! Other people might consider throwing a fabsf() in there, just to get the absolute value. – Andrew Sep 09 '13 at 12:17
-
3You need to take the time into account otherwise the speed will jitter. – meaning-matters Sep 03 '15 at 23:43
-
Other than the jittering issue, the other issue is that if I change the contentInset of the scrollView it will be registered as a fast scroll. I'm having trouble distinguishing between the two events. – John Farkerson Jun 25 '19 at 23:12
2017...
It's very easy to do this with modern Swift/iOS:
var previousScrollMoment: Date = Date()
var previousScrollX: CGFloat = 0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let d = Date()
let x = scrollView.contentOffset.x
let elapsed = Date().timeIntervalSince(previousScrollMoment)
let distance = (x - previousScrollX)
let velocity = (elapsed == 0) ? 0 : fabs(distance / CGFloat(elapsed))
previousScrollMoment = d
previousScrollX = x
print("vel \(velocity)")
Of course you want the velocity in points per second, which is what that is.
Humans drag at say 200 - 400 pps (on 2017 devices).
1000 - 3000 is a fast throw.
As it slows down to a stop, 20 - 30 is common.
So very often you will see code like this ..
if velocity > 300 {
// the display is >skimming<
some_global_doNotMakeDatabaseCalls = true
some_global_doNotRenderDiagrams = true
}
else {
// we are not skimming, ok to do calculations
some_global_doNotMakeDatabaseCalls = false
some_global_doNotRenderDiagrams = false
}
This is the basis for "skimming engineering" on mobiles. (Which is a large and difficult topic.)
Note that that is not a complete skimming solution; you also have to care for unusual cases like "it has stopped" "the screen just closed" etc etc.
May be this would be helpful
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset

- 3,233
- 1
- 23
- 20
-
want to mention, this is example from velocity output: `(0.0,-5.35356)`. Scroll by y axis, 5.35.. -> 15 points per `scrollViewDidScroll` calling :) So, 5 is very fast. – Dima Deplov Dec 03 '14 at 20:22
You can see PageControl sample code about how to get the contentOffset of scrollview.
The contentOffset
on movement can be obtained from UIScrollViewDelegate
method, named - (void)scrollViewDidScroll:(UIScrollView *)scrollView
, by querying scrollView.contentOffset
. Current speed can be calculated by delta_offset and delta_time.
- Delta_offset = current_offset - pre_offset;
- Delta_time = current_time - pre_time;

- 8,180
- 5
- 45
- 52

- 17,522
- 9
- 100
- 118
-
Oh I gotcha so real time velocity using distance over time I suppose – rolling_codes Sep 16 '10 at 11:34
-
1The current time can be obtained by CACurrentMediaTime() in the QuartzCore framework. Then you can calculate velocity by distance and time. – AechoLiu Sep 16 '10 at 13:20
Here is another smart way to do this in SWIFT :-
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if velocity.y > 1.0 || velocity.y < -1.0 && self.sendMessageView.isFirstResponder() {
// Somthing you want to do when scrollin fast.
// Generally fast Vertical scrolling.
}
}
So if you scrolling vertically you should use velocity.y and also if you are scrolling horizontally you should use velocity.x . Generally if value is more than 1 and less than -1, it represent generally fast scrolling. So you can change the speed as you want. +value means scrolling up and -value means scrolling down.

- 7,253
- 2
- 50
- 58
-
-
-
you said in your answer `So you can change the speed as you want`. So i was wondering, how do you change the speed of the scroll? – Just a coder Aug 05 '16 at 04:22
-
1I mean user scrolling speed. This functions if loop capture the scrolling speed, so i mean that you can change that speed. You can't change scrolling speed :) – Mudith Chathuranga Silva Aug 05 '16 at 04:25
-