touches methods not getting called on UIView placed inside a UIScrollView

anshul picture anshul · Mar 5, 2012 · Viewed 8.5k times · Source

I have a Custom Scroll View, subclassing UIScrollView. I have added a scroll view in my viewcontroller nib file and changed its class to CustomScrollView. Now, this custom scroll view (made from xib) is added as a subview on self.view.

In this scroll view, I have 3 text fields and 1 UIImageView(named signImageView) added from xib. On clicking UIImageView (added a TapGestureRecogniser), a UIView named signView is added on the custom scroll view. I want to allow User to sign on this view, So I have created a class Signature.m and .h, subclassing UIView and implemented the touches methods (touchesBegan, touchesMoved and touchesEnded) and initialised the signView as follows:

signView = [[Signature alloc]initWithFrame:signImageView.frame];
    [customScrollView addSubview:signView];

But when I start signing on the signView, the view gets scrolled and hence the touches methods don't get called.

I have tried adding signView on self.view instead of custom scroll view, but in that case the view remains glued to a fixed position when I start scrolling. (Its frame remains fixed in this case)

Answer

Rok Jarc picture Rok Jarc · Mar 5, 2012

Try setting canCancelContentTouches of the scrollView to NO and delaysContentTouches to YES.

EDIT:

I see that similiar question was answered here Drag & sweep with Cocoa on iPhone (the answer is exactly the same).

If the user tap-n-holds the signView (for about 0.3-0.5 seconds) then view's touchesBegan: method gets fired and all events from that moment on go to the signView until touchesEnded: is called.

If user quickly swipes trough the signView then UIScrollView takes over.

Since you already have UIView subclassed with touchesBegan: method implemented maybe you could somehow indicate to user that your app is prepared for him to sign ('green light' equivalent).

You could also use touchesEnded: to turn off this green light.

It might be better if you add signImageView as as subView of signView (instead of to customScrollView) and hide it when touchesBegan: is fired). You would add signView to customScrollview at the same place where you add signImageView in existing code instead.

With this you achieve that there is effectively only one subView on that place (for better touch-passing efficiency. And you could achieve that green light effect by un-hiding signImageView in touchesBegan:/touchesEnded:

If this app-behaviour (0.3-0.5s delay) is unacceptable then you'd also need to subclass UIScrollView. There Vignesh's method of overriding UIScrollView's touchesShouldBegin: could come to the rescue. There you could possibly detect if the touch accoured in signView and pass it to that view immediately.