I'm looking to detect if (not when) a UIScrollView
is scrolling.
i.e.
BOOL isScrolling = myscrollview.scrolling;
How would I go about implementing this? .dragging
and .decelerating
do not apply when setContentOffset:animated:
is used.
Since a scrollView has a panGesture we can check the velocity of that gesture. If the tableView was programmatically scrolled the velocity in both x and y directions is 0.0. By checking this velocity we can determine if the user scrolled the tableView because the panGesture has a velocity. Save this answer.
Adding a constraint so that the stackview and scrollview have equal widths will remove warnings from interface builder, but then scrolling will be disabled. Scrolling only happens when the content view inside the scrollview is larger than the scrollview!
In Android, a ScrollView is a view group that is used to make vertically scrollable views. A scroll view contains a single direct child only. In order to place multiple views in the scroll view, one needs to make a view group(like LinearLayout) as a direct child and then we can define many views inside it.
EDIT: This method seems to have stopped working since iOS 14. I'll try and see if I can find an alternative method, and I'll update this answer if I do.
This may be a slightly dodgy way of doing it, but I've used it in my code before and it hasn't failed me yet. :)
Swift
let isScrolling = scrollView.layer.animation(forKey: "bounds") != nil
Objective-C
BOOL isScrolling = [scrollView.layer animationForKey:@"bounds"] != nil;
In addition to self.contentOffset
the offset of a UIScrollView
is stored in the bounds.origin
property of the UIView
as well (I guess since it's a bit more convenient in lower-level code). When you call [setContentOffset:animated:]
, it's passing that off to the UIScrollView
as a CABasicAnimation
, manipulating the bounds
property.
Granted, this check will also return true if the shape of the scroll view itself is animating. In which case you may need to actually pull the bounds object out of the animation ([CAAnimation toValue]
) and do a manual compare to see if origin
itself is changing at all.
It's not the most elegant solution, but I like being able to avoid having to make use of the scroll view delegate whenever possible. Especially if the scroll view in question might be a subclass explicitly vending its delegate as part of its public API. :)
Not a very clean solution .. but should be the most reliable:
var isScrolling = false
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isScrolling = true
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate { scrollViewDidEndScrolling(scrollView) }
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
scrollViewDidEndScrolling(scrollView)
}
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
scrollViewDidEndScrolling(scrollView)
}
func scrollViewDidEndScrolling(_ scrollView: UIScrollView) {
isScrolling = false
}
I usually do this by setting a boolean variable in the scrollViewWillBeginDragging:
and scrollViewDidEndDragging:willDecelerate:
events.
UIScrollView Docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With