9
votes

I've got a view that has two subviews:

  1. Subview A, a UIView (contains other views, which contain UIButtons, views with gesturerecognizer ...)
  2. Subview B, a UIScrollView (contains some views, but has transparent regions).

The scrollview is on top of Subview A and has the full device width/height. I want the user to be able to interact - through the transparent regions - with all those buttons and gesture reconizers below the scrollview, while still being able to scroll (so passing on the hittest is out).

Seems like an easy enough task, but I can't get it to work. The scrollview is always blocking all touches.

Any idea how I would accomplish that? Thanks!

3
Why is the scroll view over the other view in the first place ? - GuybrushThreepwood
The views in the scrollview need to overlap the views underneath. - René

3 Answers

14
votes

You should subclass the UIScrollView and overwrite the following method:

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

If this method returns NO the scrollview will be "transparent" for touch events.

As you want the scrollview to be "transparent" for touch events only if the touch is in a transparent area of your scrollview, your implementation should look like:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
     return ![self isPointInsideATransparentRegion:point]; //you need to implement isPointInsideATransparentRegion to check whether the point touched is in a transparent region or not
}
2
votes

I've somewhat solved this now by adding the view that's supposed to be below the scrollview to the scrollview as the first subview, and shifting its position in scrollViewDidScroll:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self updateBottomViewPosition];
}

- (void)updateBottomViewPosition {
    CGPoint contentOffset = _mainScrollView.contentOffset;

    CGFloat y = MAX(contentOffset.y, 0);

    CGRect frame = _bottomPage.frame;
    if (y != frame.origin.y) {
        frame.origin.y = y;
        _leadPage.frame = frame;
    }
}

This works, but it's probably not as elegant as possible.

0
votes

Based in René's answer, this works if the background view is fixed (f.e. at the top of the view) and the bottom scroll has bounce.

#pragma mark - Scroll delegate

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self updateBottomViewPosition];
}

- (void)updateBottomViewPosition {
    CGPoint contentOffset = self.scrollView.contentOffset;

    CGFloat y = MAX(contentOffset.y, 0);


    CGRect frame = self.fixedView.frame;
    if (y > 0) {
        frame.origin.y = y;
    } else {
        frame.origin.y = 0;
    }
    self.fixedView.frame = frame;
}

You can use this to create also a nice paralax effect, if you don't want it to be fixed you should change the y value to your wanted transition movement.