Reputation: 14484
I have a scroll view that is programmed so that if you pull down more than 100px (i.e into the negative y content offset and with bounces
enabled) then let go, a view at the top of the scroll view gets larger 100px larger (pushing everything else down). To make the transition smooth I'm trying to adjust the content offset of the scrollview by 100px at this point, like this:
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
{
if scrollView.contentOffset < -100
{
scrollView.contentOffset.y += 100 //
makeTopViewTaller()
}
}
However, the change in the contentOffset doesn't stick. By logging the content offset in the scrollViewDidScroll()
method I can see that the y value changes for a moment, but then goes back to where it was when the dragging ended.
Is there any way to force the content offset to change, then let the UIScrollView's natural bounce decelaration to apply to the new value?
Upvotes: 1
Views: 1127
Reputation: 14484
I tried a whole bunch of different approaches to this problem, but the one that eventually worked involved creating a subclass of the UIScrollView (in my case, actually a UICollectionView) and overriding the setter for the contentOffset
property. Here's my subclass:
class MyCollectionView : UICollectionView
{
var isTransitioning:Bool = false
var initialTransitioningY:CGFloat = 0
override var contentOffset:CGPoint
{
get
{
return super.contentOffset
}
// This custom setter is to make the transition to the large header state smooth
set
{
if(isTransitioning && initialTransitioningY < 0)
{
var oy = newValue.y
if(oy == 0 && contentOffset.y < -10) // This is to avoid a flicker when you first call 'reloadData' on the collection view, which sets the contentOffset.y to 0, then returns to it's previous state
{
oy = contentOffset.y
}
super.contentOffset = CGPointMake(newValue.x, (initialTransitioningY + 100) * (oy / initialTransitioningY))
}
else
{
super.contentOffset = newValue
}
}
}
}
When the user has pulled passed the transition point (100px in my case) and let go the scrollViewWillEndDragging
method is called and the isTransitioning
property is set to true
and initialTransitioningY
set to the collection view's current content offset. When scrollViewDidEndDecelerating
is called the isTransitioning
property is set back to false.
Works a charm.
Upvotes: 1