SETUP
So I have a UIScrollView
at the top of the view with a UIPanGestureRecognizer covering the whole view.
GOAL
When the user pan with a touch, I want the UIScrollView
to scroll in a way that the pan gesture within the scroll view picks up the touches.
NOTE
A few years back, on a WWDC session video, Apple showed us how to do this using the pull-down gesture to search on the Home Screen. They showed how the pull-down pan gesture actually gets picked up by the scroll view inside the search results panel. Somehow, now I can’t locate this video.
2
Answers
The WWDC video I was referring to above was "`Advanced Scrollviews and Touch Handling Techniques" from 2014. For some reason, Apple has removed the session.
https://www.wwdcnotes.com/notes/wwdc14/235/
The key lines here were:
They are adding the scrollview's pan gesture to another view.
As I mentioned in the comments, there are several approaches to this… which to use depends on what else you need to do with other UI elements.
So, absent any additional information, here are two ways to go about this.
Let’s start with a "Base" view controller class:
It looks like this when run by itself:
A scroll view with green background (so we can see it)… the scroll content is a vertical stack view with 12 labels (so we have something to scroll).
So far, nothing new. You can scroll the scroll view, but only dragging inside it.
The First approach is to create a subclass of that "base" controller, but we’ll add a
UIPanGestureRecognizer
to the controller’s view:Now, dragging anywhere outside the scroll view will set the content offset of the scroll view’s content, so it will look like you are dragging inside it.
Note that this example will "bounce" the content if we drag past the top or bottom, but – since you didn’t say anything about your goal – it does not mimic a scroll view’s deceleration. You could do that by calculating the gesture’s velocity, magnitude, etc.
A Second approach would be to subclass
UIScrollView
and overridehitTest(...)
:So this controller (again subclassing the "base" controller) uses a
HTScrollView
in place of the defaultUIScrollView
:Again, dragging anywhere outside the scroll view will look just like you are dragging inside it… with the added advantage of getting the built-in deceleration and bouncing.
The drawback here is that you won’t be able to interact with any subviews in the scroll view itself – such as buttons.
To overcome that, we’d need to use a more complete
hitTest(...)
override which would loop through the scroll view’s subviews and return the view/control appropriately.