4

I have a UIImageView that is added as a subview. It shows up when a button is pressed.

When someone taps outside of the UIImageView in any part of the application, I want the UIImageView to go away.

@interface SomeMasterViewController : UITableViewController <clip>

<clip>

@property (strong, nonatomic) UIImageView *someImageView;

There are some hints in stackoverflow and Apple's documentation that sound like what I need.

However, I want to check my approach here. It's my understanding that the code needs to

  1. Register a UITapGestureRecognizer to get all touch events that can happen in an application

  2. UITapGestureRecognizer should have its cancelsTouchesInView and delaysTouchesBegan and delaysTouchesEnded set to NO.

  3. Compare those touch events with the someImageView (how? Using UIView hitTest:withEvent?)

Update: I am registering a UITapGestureRecognizer with the main UIWindow.

Final Unsolved Part

I have a handleTap:(UITapGestureRecognizer *) that the UITapGestureRecognizer will call. How can I take the UITapGestureRecognizer that is given and see if the tap falls outside of the UIImageView? Recognizer's locationInView looks promising, but I do not get the results I expect. I expect to see a certain UIImageView when I click on it and not see the UIImageView when I click in another spot. I get the feeling that the locationInView method is being used wrong.

Here is my call to the locationInView method:

- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateEnded) {
        NSLog(@"handleTap NOT given UIGestureRecognizerStateEnded so nothing more to do");
        return;        
    }

    UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
    CGPoint point = [gestureRecognizer locationInView:mainWindow];
    NSLog(@"point x,y computed as the location in a given view is %f %f", point.x, point.y);

    UIView *touchedView = [mainWindow hitTest:point withEvent:nil];
    NSLog(@"touchedView = %@", touchedView); 
}

I get the following output:

<clip>point x,y computed as the location in a given view is 0.000000 0.000000

<clip>touchedView = <UIWindow: 0x8c4e530; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <UIWindowLayer: 0x8c4c940>>
Cœur
  • 37,241
  • 25
  • 195
  • 267
finneycanhelp
  • 9,018
  • 12
  • 53
  • 77

2 Answers2

4

I think you can just say [event touchesForView:<image view>]. If that returns an empty array, dismiss the image view. Do this in the table view controller's touchesBegan:withEvent:, and be sure to call [super touchesBegan:touches withEvent:event] or your table view will completely stop working. You probably don't even need to implement touchesEnded:/Cancelled:..., or touchesMoved:....

UITapGestureRecognizer definitely seems like overkill in this case.

samson
  • 1,152
  • 11
  • 23
  • Thanks! BTW, You mean touchesBegan:withEvent instead of "touchesBegan:touches forEvent:event" right or am I missing something? :) – finneycanhelp Apr 06 '12 at 12:03
  • I liked the suggestion. However, the touchesBegan:withEvent is not getting called in the UITableViewController. I think I am running into http://stackoverflow.com/questions/6286230/touches-began-in-uitableviewcontroller – finneycanhelp Apr 06 '12 at 12:40
  • Yes, you're right. Twice. Not sure how to fix this, I'll try it out and get back to you. Let us know if you figure it out! – samson Apr 06 '12 at 18:17
  • (Also, you should take a look at [this post about UIImageView overlays](http://stackoverflow.com/questions/10041854/transparent-uiimageview-in-front-of-all-the-ui/10041967#10041967). I think, if you want the image to be __above__ the table view, you should definitely consider the approach therein, which uses a new UIWindow. You'll also probably have to subclass UIImageView in this case to catch the touches...) – samson Apr 06 '12 at 18:25
  • A slightly different and simple idea came out of another question: http://stackoverflow.com/questions/10067059/why-does-the-ipad-become-nonresponsive-after-uigesturerecognizer-is-added-to-uiw "create a UIWindow subclass" – finneycanhelp Apr 29 '12 at 15:48
2

You can use touch functions to do that:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

when user touch the screen first your touchBegan function is called.

in touchBegan:

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

    CGPoint pt = [[touches anyObject] locationInView:self]; 
}

so you have the point that user touched.Then you must find that the point is in your UIImageView or not.

But if you can give tag to your UIImageViews. That will be pretty much easy.

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

      UITouch *touch = [touches anyObject ];

      if( yourImageView.tag==[touch view].tag){

         [[self.view viewWithTag:yourImageView.tag] removeFromSuperView];
         [yourImageView release];

      }
}
beryllium
  • 29,669
  • 15
  • 106
  • 125
mhunturk
  • 296
  • 2
  • 12