Search code examples
iphoneobjective-cinputuser-inputtouches

Disable touch events on certain areas of iPhone screen


I want to disable touches on all areas of the screen apart from a specific few points (e.g buttons). I.e. I don't want 'touchesBegan' to trigger at all when I tap anything other than a button. Calling

    self.view.userInteractionEnabled = NO;

has the desired effect for not registering touches, but then of course I can't tap any buttons. I basically want the button to still work, even if there are 5 points touching the screen, i.e. all touch inputs have been used up, and the button represents the 6th.

Is this possible?

I've tried inserting a view with userInteraction disabled below my buttons, but it still registers touches when the user taps the screen. It seems the only way to disable touch registering is to do so on the entire screen (on the parent UIView).

UPDATE: I've tried using gesture recognizers to handle all touch events, and ignore those that don't qualify. Here is my code:

@interface ViewController : UIViewController <UIGestureRecognizerDelegate>

...

    - (void)viewDidLoad
{
    [super viewDidLoad];
    UIGestureRecognizer *allRecognizer = [[UIGestureRecognizer alloc] initWithTarget:self action:nil];
    allRecognizer.delegate = self;
    [self.view addGestureRecognizer:allRecognizer];
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint coords = [touch locationInView:self.view];
    NSLog(@"Coords: %g, %g", coords.x, coords.y);
    if (coords.y < 200) {
    [self ignoreTouch:touch forEvent:nil];
    return TRUE;
}
return FALSE;

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"%i touch(es)", [touches count]);
}

However the screen still 'reads' the touches, so if I place 5 fingers down, the 6th one won't trigger a button press...


Solution

  • You need to set up an invisible UIButton and lay it between the view that should not register touches and the UIButtons that should still be active.

    Now you need to set the invisible button's 'userInteractionEnabled':

    //userInteractionEnabled == NO  => self.view registeres touches
    //userInteractionEnabled == YES => self.view doesn't register touches
    [_invisibleButton setUserInteractionEnabled:NO];
    

    What really matters in this solution is that both - the invisible and the visible buttons are direct subviews of the VC's view.

    You can download an example project from my dropbox: https://dl.dropboxusercontent.com/u/99449487/DontTapThat.zip

    However this example just prevents the handling of certain touches. Completly ignoring input isn't technically possible: Third party apps are not responsible for for detecting input. They are just responsible for handling input. The detection of touch input is done iOS.

    The only way to build up a case like you describe it in the comments is to hope that iOS won't interpret the input of your case as a "finger" because it's most likely going to cover an area that's way bigger than a finger.

    So in conclusion the best way would be to change the material of the case you're about to build or at least give it a non conductive coating. From a third party developers point of view there is no way to achieve your goals with software if there is a need for 5 fingers as described in the comments.