Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIButton behind UIScrollView

I have a UIButton behind a UIScrollView. The scroll's background is transparent and the button is in the lower right corner. So it is visible.

The problem is that the UIButton does not respond to any touch events when it is below the scroll. What would it require to make it respond to touch events in this scenario?

Thank you

like image 721
vgr Avatar asked Nov 27 '22 20:11

vgr


2 Answers

You should use the +touchesBegan method to pass on the touches to the next object.
Here is a example of how you would do this:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
printf("MyButton touch Began\n");
[self.nextResponder touchesBegan:touches withEvent:event]; 
}

Heres some more info on the responder chain:

  1. A Bit About the Responder Chain (http://iphonedevelopment.blogspot.com)

  2. Cocoa Application Competencies for iOS: Responder Object (http://developer.apple.com)

like image 181
Sam Baumgarten Avatar answered Nov 29 '22 08:11

Sam Baumgarten


I had this problem today, after much time investigating is pretty difficult to achieve, because you can lose the dragging ability in exchange for the buttons click event.

However: I ended up with this, a UIScrollView subclass whose receives the button or buttons to which it is interested in catching the event.

The key is to use [(UIControl*)view sendActionsForControlEvents: UIControlEventTouchUpInside];, because calling touchesBegan method not always works as expected. This won't change the GUI as you press the button but you can implement that as needed in a custom method.

@implementation ForwardScrollView

@synthesize responders = _responders;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        _touchesEnabled = YES;
    }
    return self;
}


- (id)initWithCoder:(NSCoder *)aDecoder {
    if ( self = [super initWithCoder: aDecoder]) {
        _touchesEnabled = YES;
    }
    return self;
}


- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    return _touchesEnabled;
}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    _touchesEnabled = NO;
    UIWindow *window = [UIApplication sharedApplication].delegate.window;
    for(UITouch *touch in touches) {
        CGPoint point = [touch locationInView:self];
        point = [window convertPoint:point fromView:self];
        UIView *view = [window hitTest:point withEvent:event];

        UITouch* touch = [touches anyObject];
        UIGestureRecognizer* recognizer;
        if ([touch gestureRecognizers].count > 0) {
            recognizer = [touch gestureRecognizers][0];
        }

        if ( (!recognizer || ![recognizer isMemberOfClass:NSClassFromString(@"UIScrollViewPanGestureRecognizer")])  && [_responders containsObject: view]) {
            [(UIControl*)view sendActionsForControlEvents: UIControlEventTouchUpInside];
        }

    }
    _touchesEnabled = YES;

}

@end

The counting on the gestureRecognizers is to avoid the pan gesture that could trigger the button when no real tap is made.

like image 45
htafoya Avatar answered Nov 29 '22 09:11

htafoya