Question

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...

Was it helpful?

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.

OTHER TIPS

There is couple of methods in UIView that you can override:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;   // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;   // default returns YES if point is in bounds

This should prevent to call touchBegin and other methods.

Regards.

I have a nice solution for this. What ever the area you want to hide the interaction place a transparent button on top of the area.

touchesBegan is a default method so it must call all the time when touch happens on view so there is no way-out, But you can still do one thing set

self.buttonPlayMusic.userInteractionEnabled = FALSE; 

for the object you don't need touch may be this could be help you with your desired output.

Have you tried using a UIScrollView as the background ? i.e the area where you do not want touch events to be fired.

UIScrollView does not call the touch methods.

You can add UIImageView Control on that area where you want to disable touch event.you can add UIImageView object as top of self.view subViews.

Example //area -- is that area where you want to disable touch on self.view

UIImageView *imageView=[[UIImageView alloc]initWithFrame:area];

[self.view addSubView:imageView];

You touchDelegate will always call in this way, but if you are doing some task on touch then you can do your task like this way.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *touch = [touches anyObject];

    UIButton *touchObject=(UIButton*)[touch view];

    if ([touchObject isKindOfClass:[UIButton class]])
    {
        //Do what ever you want on button touch
    }
    else{
        return;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top