Scrolling the Scroll View Content
The most common method of initiating the scrolling of a scroll view is a direct manipulation by the user touching the screen and dragging with their finger. The scroll content then scrolls in response to the action. This gesture is referred to as a drag gesture.
A variation of the drag gesture is the flick gesture. A flick gesture is a quick movement of a user’s finger that makes initial contact with the screen, drags in the direction of the desired scroll, and then lifts from the screen. This gesture not only causes scrolling, it imparts a momentum, based on the speed of the user’s dragging action, that causes scrolling to continue even after the gesture is completed. The scrolling then decelerates over a specified period of time. The flick gesture allows users to move large distances with a single action. At any time during the deceleration, the user can touch the screen to stop the scrolling in place. All this behavior is built into
UIScrollView and requires no implementation on the part of the developer.
But sometimes it’s necessary for the application to scroll content programmatically, for example, to display a specific portion of a document. In those cases,
UIScrollView provides the required methods.
UIScrollView delegate protocol
UIScrollViewDelegate provides methods that allow your application to track the scrolling progress and respond as appropriate to the specific needs of your application.
Scrolling the content of a scroll view is not always in response to the user’s finger dragging or flicking the screen. There are times when your application will need to scroll to a certain content offset, so that a specific rectangular area is exposed, or to the top of the scroll view.
UIScrollView provides methods to perform all these actions.
Scrolling to a Specific Offset
Scrolling to a specific top-left location (the
contentOffset property) can be accomplished in two ways. The
setContentOffset:animated: method scrolls the content to the specified content offset. If the animated parameter is
YES, the scrolling will animate from the current position to the specified position at a constant rate. If the animated parameter is
NO, the scrolling is immediate and no animation takes place. In both cases, the delegate is sent a
scrollViewDidScroll: message. If animation is disabled, or if you set the content offset by setting the
contentOffset property directly, the delegate receives a single
scrollViewDidScroll: message. If animation is enabled, then the delegate receives a series of
scrollViewDidScroll: messages as the animation is in progress. When the animation is complete, the delegate receives a
Making a rectangle visible
It is also possible to scroll a rectangular area so that it is visible. This is especially useful when an application needs to display a control that is currently outside the visible area into the visible view. The
scrollRectToVisible:animated: method scrolls the specified rectangle so that it is just visible inside the scroll view. If the animated parameter is
YES, the rectangle is scrolled into view at a constant pace. As with
setContentOffset:animated:, if animation is disabled, the delegate is sent a single
scrollViewDidScroll: message. If animation is enabled, the delegate is sent a series of
scrollViewDidScroll: messages as animation progresses. In the case of
scrollRectToVisible:animated: the scroll view’s tracking and dragging properties are also
If animation is enabled for
scrollRectToVisible:animated:, the delegate receives a
scrollViewDidEndScrollingAnimation: message, providing notification that the scroll view has arrived at the specified location and animation is complete.
Scroll To Top
If the status bar is visible a scroll view can also scroll to the top of the content in response to a tap on the status bar. This practice is common in applications that provide a vertical representation of data. For example, the Photos application supports scroll to top, both in the album selection table view and when viewing thumbnails of the photos in an album and most
UITableView implementations (a subclass of
UIScrollView) also support scroll to top.
Your application enables this behavior by implementing the delegate method the scroll view property
scrollViewShouldScrollToTop: and return
YES. This delegate method allows fine-grained control over which scroll view will scroll to the top if there are multiple scroll views on the screen at one time by returning the scroll view to scroll.
When scrolling is complete, the delegate is sent a
scrollViewDidScrollToTop: message, specifying the scroll view.
Delegate Messages Sent During Scrolling
As scrolling occurs, the scroll view tracks state using the
zooming properties. In addition, the
contentOffset property defines the point in the content that is visible at the top left of the scroll view’s bounds. The following table describes each of the state properties:
It isn’t necessary to poll these properties to determine the action in progress because the scroll view sends a detailed sequence of messages to the delegate, indicating the progress of the scrolling action. These methods allow your application to respond as necessary. The delegate methods can query those state properties to determine why the message was received or where the scroll view currently is.
The Simple Approach: Tracking The Start and Completion Of A Scroll Action
If your application is interested only in the beginning and ending of the scrolling process, you can implement only a small subset of the possible delegate methods.
scrollViewWillBeginDragging: method to receive notification that dragging will begin.
To determine when scrolling is complete you must implement two delegate methods:
scrollViewDidEndDecelerating:. Scrolling is completed either when the delegate receives the
scrollViewDidEndDragging:willDecelerate: message with
NO as the decelerate parameter, or when your delegate receives the
scrollViewDidEndDecelerating: method. In either case, scrolling is complete.
The Complete Delegate Message Sequence
When the user touches the screen the tracking sequence begins. The
tracking property is set to
YES immediately, and remains
YES as long as the user’s finger is in contact with the screen, regardless of whether they are moving their finger.
If the user’s finger remains stationary and the content view responds to touch events, it should handle the touch, and the sequence is complete.
However, if the user moves the finger, the sequence continues.
When the user begins to move their finger to initiate scrolling the scroll view first attempts (assuming the default values of the scroll view) to cancel any in progress touch handling, if it is attempting to do so.
The scroll view’s
dragging property is set to
YES, and its delegate is sent the
As the user drags their finger, the
scrollViewDidScroll: message is sent to the delegate. This message is sent continuously as scrolling continues. Your implementation of this method can query the scroll view’s
contentOffset property to determine the location of the top-left corner of the scroll view bounds. The
contentOffset property is always the current location of the top-left corner of the scroll bounds, whether scrolling is in progress or not.
If the user performs a flick gesture, the
tracking property is set to
NO, because in order to perform a flick gesture, the user’s finger breaks contact with the screen after the initial gesture begins the scroll. At this time the delegate receives a
scrollViewDidEndDragging:willDecelerate: message. The deceleration parameter will be
YES as the scrolling decelerates. The deceleration speed is controlled by the the
decelerationRate property. By default, this property is set to
UIScrollViewDecelerationRateNormal, which allows scrolling to continue for a considerable time. You can set the rate to
UIScrollViewDecelerationFast to cause the deceleration to take significantly less time, the scrolled distance after the flick gesture to be much shorter. As a view decelerates, the
decelerating property of the scroll view is
If the user drags, stops dragging and then lifts their finger from the screen the delegate receives the
scrollViewDidEndDragging:willDecelerate: message, however the deceleration parameter is
NO. This is because no momentum has been imparted on the scroll view. Because the user’s finger is no longer in contact with the screen the
tracking property value is
If the decelerate parameter of the
scrollViewDidEndDragging:willDecelerate: message is
NO, then the scroll view delegate will receive no more delegate messages for this drag action. The scroll view decelerating property also now returns a value of
There is one other condition that causes the
scrollViewDidEndDragging:willDecelerate: message to be sent to the delegate, even if the user has lifted their finger when is stationary. If the scroll view is configured to provide the visual cue of bouncing when the user drags the content past the edge of the scrolling area, the
scrollViewDidEndDragging:willDecelerate: message is sent to the delegate with
YES as the decelerate parameter. Bouncing is enabled when the
bounces property is
YES (the default state). The
alwaysBounceHorizontal properties do not affect the behavior of the scroll view when
YES, they allow bouncing when the
contentSize property value is smaller than the scroll view bounds.
Regardless of the condition that caused the scroll view to receive the
scrollViewDidEndDragging:willDecelerate: message, if the decelerate parameter is
YES, the scroll view is sent the
scrollViewWillBeginDecelerating: message. During deceleration, the delegate continues to receive the
scrollViewDidScroll: message, although the
dragging values are now both
decelerating property continues to be
Finally, when the scroll view deceleration completes, the delegate is sent a
scrollViewDidEndDecelerating: message, the
decelerating property has a value of
NO, and the scrolling sequence is complete.