'How to pass touches from UIView to UIScrollView

Similar to this thread and many others, I've got a view controller with a NIB file which has this layout...

  • a. UIView (480 x 320) - stores a background image
  • b. UIScrollView (480 x 220) - Is a level selector scrollview
  • c. UIView (480 x 320) - contains a foreground animated graphic

All three items above are subviews of the main View in the NIB. UIView (c) is the full size of the iPhone screen and on top of the hierarchy. On it, I've placed a character which animates based on the current touch position in that view. However the issue is that with this view receiving touches, I cannot get the touches to the ScrollView (b) below it. I still need to use the touches at (c) but also need to pass relevant touches / swipes to the UIScrollView below afterwards.

Can anyone advise how this can be done? I've read various posts on using hittest but don't want to offset the touches completely, I just need to forward them after so that the scrollview still works as normal.

Thanks,



Solution 1:[1]

Here's an easier solutions that worked well for me:

In view C (the foreground view that is above the UIScrollView), make the width and height both 0 (so that the view is no longer technically on top of the scrollview) and set clipsToBounds = NO (so that the contents of view C still show up on top of the scrollview). It worked like a charm for me.

 self.viewC.clipsToBounds = NO;
 CGRect frame = self.viewC.frame;
 self.viewC.frame = CGRectMake(frame.origin.x, frame.origin.y, 0, 0);

Note that if view C contains interactive controls then they will no longer work.

Solution 2:[2]

Few more options:

  1. Consider setting isUserinteractionEnabled to false for the views hiding/=above the scrollview. I think this is for "c. UIView (480x320)" See answer here https://stackoverflow.com/a/52054954/4970749. If false, touches get skipped and handed down to subviews below.

  2. The animation on top "c. UIView (480x320)" isExclusiveTouch might be set to true. Set it to the default false value. Apple documentation: https://developer.apple.com/documentation/uikit/uiview/1622453-isexclusivetouch

  3. Gesture recognizers also allow multiple touches to happen. UIGestureRecognizerDelegate has func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool

  4. Gesture recognizers part 2 -- func gestureRecognizerShouldBegin(_) https://stackoverflow.com/a/11968812/4970749

Solution 3:[3]

Subclass UIScrollVeiw and override the touchesShouldCancelInContentView: method like this:

-(BOOL)touchesShouldCancelInContentView:(UIView *)view
{

    if ([view isKindOfClass:[UIButton class]]) {//or whatever class you want to override
        return YES;
    }

    if ([view isKindOfClass:[UIControl class]]) {
        return NO;
    }

    return YES;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 bbrame
Solution 2 bubbaspike
Solution 3