Hide View by click on any part of the screen in iphone - iphone

I have a View which is the subView of the main view in iphone app I want that when subView is shown and user taps on part of the screen except the subView then subView should hide.
Here is the code which I got but it does not hide it :
UITapGestureRecognizer *tapGR;
tapGR = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)] autorelease];
tapGR.numberOfTapsRequired = 1;
[self.View addGestureRecognizer:tapGR];
// Add a delegate method to handle the tap and do something with it.
-(void)handleTap:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded) {
// handling code
[myViewSheet removeFromSuperView];
}
}

implement UIGestureRecognizerDelegate protocol:
.h:
#interface YourView : UIView<UIGestureRecognizerDelegate>
.m:
#implementation YourView{
UIView * subview;
}
...
subview = [[UIView alloc]initWithFrame:CGRectMake(0, 200, 320, 200)];
[self addSubview:subview];
UITapGestureRecognizer *tapGR;
tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapGR.numberOfTapsRequired = 1;
tapGR.delegate = self;
[self addGestureRecognizer:tapGR];
...
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view == subView)
{
return NO;
}
else
{
return YES;
}
}

You probably need to set userInteractionEnabled = YES on your main view (The one to which you are attaching the gesture recognizer.)

Related

How do I detect a tap anywhere in the view?

I have a tutorial for my app, which should display only the first time the app is opened and should be tapped to dismiss.
I am initializing a UITapGestureRecognizer in my viewDidLoad:
tapper_tut = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
tapper_tut.cancelsTouchesInView = FALSE;
[self.view addGestureRecognizer:tapper_tut];
and I have an IBAction to detect the tap and set the tutorial to hidden:
- (IBAction)dismiss_tut{
if (????????????????) {
_tutorial.hidden = YES;
}
}
But I have no idea what to put in the if statement condition, or if this is even that right way to go about this.
How would I dismiss a UIImageView on a tap?
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[self.view addGestureRecognizer:gr];
// if not using ARC, you should [gr release];
// mySensitiveRect coords are in the coordinate system of self.view
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.view];
if (CGRectContainsPoint(mySensitiveRect, p)) {
NSLog(#"got a tap in the region i care about");
} else {
NSLog(#"got a tap, but not where i need it");
}
}
You can make viewDidLoad like this
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
/* Create the Tap Gesture Recognizer */
self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTaps:)];
/* The number of fingers that must be on the screen */
self.tapGestureRecognizer.numberOfTouchesRequired = 1;
/* The total number of taps to be performed before the gesture is recognized */
self.tapGestureRecognizer.numberOfTapsRequired = 1;
/* Add this gesture recognizer to the view */
[self.view addGestureRecognizer:self.tapGestureRecognizer];
}
To detect the taps you can make the method like this.
- (void) handleTaps:(UITapGestureRecognizer*)paramSender
{
NSUInteger touchCounter = 0;
for (touchCounter = 0;touchCounter < paramSender.numberOfTouchesRequired;touchCounter++)
{
CGPoint touchPoint =[paramSender locationOfTouch:touchCounter inView:paramSender.view];
NSLog(#"Touch #%lu: %#",(unsigned long)touchCounter+1, NSStringFromCGPoint(touchPoint));
}
}
you have to declare .h file as "UIGestureRecognizerDelegate"
you have getting tap of gesture as two way as given below steps.
1) Call delegate method of GestureRecognizer (not given action )
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil]; // not given action.
recognizer.numberOfTouchesRequired=1;// here how many tap you want set it
[self.view addGestureRecognizer:recognizer];
recognizer.delegate = self;
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
//whatever you want write code here
return NO;
}
2) given action
UITapGestureRecognizer *oneTouch=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(Addphoto)];
[oneTouch setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:oneTouch];
-(IBAction)Addphoto
{
//whatever you want write code here
}
may be it will help .
I think u need to detect the first time launch of the application which u can do with following
![[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"]
Put this in your if statement .

Multiple gestureRecognizers on views- one shouldn't pass touch

On parentClass(inheriting from UIView) i have:
[self addGestureRecognizer:_tapGesture]; // _tapGesture is UITapGestureRecognizer, with delegate on parentClass
On someClass:
[_myImageView addGestureRecognizer:_imageViewGestureRecognizer]; // _imageViewGestureRecognizer is UITapGestureRecognizer, with delegate on someClass
The problem is that when i tap on myImageView both gesture recognizers are firing. I want only _imageViewGestureRecognizer to work.
I've tried:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch {
UIView *gestureView = recognizer.view;
CGPoint point = [touch locationInView:gestureView];
UIView *touchedView = [gestureView hitTest:point withEvent:nil];
if ([touchedView isEqual:_imageViewGestureRecognizer]) {
return NO;
}
return YES;
}
But it ofc doesn't take upon consideration gesture recognizer from super class.
I did this little test and it worked perfectly...
#implementation View
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.backgroundColor = [UIColor whiteColor];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped1)];
[self addGestureRecognizer:tap];
UIImageView* img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"test.png"]];
img.userInteractionEnabled = YES;
img.frame = CGRectMake(0, 0, 100, 100);
[self addSubview:img];
UITapGestureRecognizer* tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped2)];
[img addGestureRecognizer:tap2];
return self;
}
-(void)tapped1 {
NSLog(#"Tapped 1");
}
-(void)tapped2 {
NSLog(#"Tapped 2");
}
#end
What you wanted was iOS's default behaviour. Once a subview has taken care of a touch, its superview won't receive the touch anymore. Did you set userInteractionEnabled on the imageView?

UITapGestureRecognizer for UIImageView on UIScrollView never called iOS5

I am adding a UIImageView as a subview to a UIScrollView then i set the image.
Im trying to to use UITapGestureRecognizer.
The selector of the UITapGestureRecognizer is never called in iOS 5 (in iOS 6 it DOES!).
Tried many variations. this is my code:
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(index*(IMAGE_WIDTH+10), 10.0, IMAGE_WIDTH, IMAGE_HEIGHT)];
[imgView setImageWithURL:[NSURL URLWithString:meal.RecommendedImageURL] placeholderImage:[UIImage imageNamed:#""]];
imgView.layer.cornerRadius = 4;
[imgView.layer setMasksToBounds:YES];
[imgView setUserInteractionEnabled:YES];
[imgView setMultipleTouchEnabled:YES];
[scrollView addSubview:imgView];
if (IOS_NEWER_OR_EQUAL_TO_5)
{
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
[imgView addGestureRecognizer:tapGestureRecognizer];
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.enabled = YES;
tapGestureRecognizer.delegate = self;
[tapGestureRecognizer setCancelsTouchesInView:NO];
}
this is my selector which is only called in iOS5:
- (void) imageTapped: (UITapGestureRecognizer *)recognizer
{
//Code to handle the gesture
UIImageView *tappedImageView = (UIImageView*)recognizer.view;
GGFullscreenImageViewController *vc = [[GGFullscreenImageViewController alloc] init];
vc.liftedImageView = tappedImageView;
vc.liftedImageView.contentMode = UIViewContentModeScaleAspectFit;
if (IOS_NEWER_OR_EQUAL_TO_5) {
[self.parentViewController presentViewController:vc animated:YES completion:nil];
}
else
{
[self.parentViewController presentModalViewController:vc animated:YES];
}
}
In addition to that, i tried to setCancelsTouchesInView to YES in my UIScrollView but it doesn't work either.
Thanks for your help!
try to add Gesture in Scrollview then check iskind of class image view
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
[scrollview addGestureRecognizer:tapGestureRecognizer];
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.enabled = YES;
tapGestureRecognizer.delegate = self;
[tapGestureRecognizer setCancelsTouchesInView:NO];
- (BOOL)gestureRecognizer:(UITapGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// test if our control subview is on-screen
if ([touch.view isKindOfClass:[UIImageView class]]) {
// we touched a button, slider, or other UIControl
return YES;
}return NO;
}
Implement the 3 methods of UIGestureRecognizerDelegate & return default values:
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
Ok i solved it very EASILY!
the problem was setting the delegate of the UITapGestureRecognizer to self.
when i removed the delegate = self, it started working :)
Thanks for your assistance

Dimming the main view when called Popover

There is a basic form, pressing button call method performSegueWithIdentifier which shows the popover window. How could I black out (dim) the main view window until the popover is active?
I've tried to use the library SVProgressHUD like this:
- (IBAction)publishButtonAction:(id)sender {
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack];
[self performSegueWithIdentifier:#"fbshareSigue" sender:self];
[SVProgressHUD dismiss];
}
Obtained for a split second - until there is a popover-window.
Where must I insert this code, if I try this?:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"fbshareSigue"]) {
OFAFBShareViewController *svc = (OFAFBShareViewController *) [segue destinationViewController];
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
svc.postBlock = self.postInitBlock;
[svc setClosePopWindow:[popoverSegue popoverController]];
}
}
- (IBAction)publishButtonAction:(id)sender {
UIView *dimView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
dimView.backgroundColor = [UIColor blackColor];
dimView.alpha = 0.5f;
dimView.tag = 1111;
dimView.userInteractionEnabled = NO;
[self.view addSubview:dimView];
[self performSegueWithIdentifier:#"fbshareSigue" sender:self];
}
/* This code should be put in the other method where you are removing the popup.. Because it will remove the dim view. here is the wrong place for this code*/
/* for (UIView *view in [self.view subviews]) {
if (view.tag == 1111) {
[view removeFromSuperview];
}
}*/
Dim doesn't work...
====================
I have View OFAResultViewController that calling Popover (OFAFBShareViewController):
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"fbshareSigue"]) {
OFAFBShareViewController *svc = (OFAFBShareViewController *) [segue destinationViewController];
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
svc.postBlock = self.postInitBlock;
[svc setClosePopWindow:[popoverSegue popoverController]];
}
}
- (IBAction)publishButtonAction:(id)sender {
UIView *dimView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
dimView.backgroundColor = [UIColor blackColor];
dimView.alpha = 0.5f;
dimView.tag = 1111;
dimView.userInteractionEnabled = NO;
[self.view addSubview:dimView];
[self performSegueWithIdentifier:#"fbshareSigue" sender:self];
}
...
In OFAFBShareViewController I'm trying to close the dim view:
...
- (IBAction)cancelButtonAction:(id)sender {
[closePopWindow dismissPopoverAnimated:YES];
for (UIView *view in [self.view subviews]) {
if (view.tag == 1111) {
[view removeFromSuperview];
}
}
...
But it doesn't work again...
You can use the following code, when you display the popup.
In OFAFBShareViewController
- (void) loadView
{
[super loadView];
UIView *dimView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
dimView.backgroundColor = [UIColor blackColor];
dimView.alpha = 0.5f;
dimView.tag = 1111;
dimView.userInteractionEnabled = NO;
[self.view addSubview:dimView];
}
After popup removed, delete this view from super view using the tag.
After iOS 5.0 there is a public API method also introduced:
======================================================
To remove the view you can use this code:
for (UIView *view in [self.view subviews]) {
if ([view.tag == 1111]) {
[view removeFromSuperview];
}
}
Leave your Remove Dim View code as it is. Only Change super.view to self.view again.
It'll work for you then.
Hope it works for you...
When you create the popover, add a dim view to the current view, and add the current view as a UIPopoverControllerDelegate of the popover controller:
Add the dimView:
let dimView = UIView(frame: view.frame)
view.addSubview(dimView)
dimView.backgroundColor = UIColor.blackColor()
dimView.alpha = 0.5
dimView.tag = 1234
dimView.userInteractionEnabled = false
view.addSubview(dimView)
Add the origin view as delegate of the popoverController:
popoverViewController!.delegate = self
Then, in order to remove the dimView when the popover is dismissed, set the current view as implementing the UIPopoverControllerDelegate, and implement the popoverControllerDidDismissPopover func. Inside this function, remove the dimView:
extension MyOriginViewController: UIPopoverControllerDelegate {
func popoverControllerDidDismissPopover(popoverController: UIPopoverController) {
for subView in view.subviews {
if subView.tag == 1234 {
subView.removeFromSuperview()
}
}
}
}

Limit tap gesture to scrollview and not the button placed upon it

I have a scroll view and a button placed over it , When i add a tap gesture recognizer the button does not work. Is there any way of limiting the tap only to scroll view and not to the button, so that the button functions normally.
here is my code
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesture:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[scroll addGestureRecognizer:tap];
[tap release];
- (void)tapGesture:(UIGestureRecognizer*)gesture{
NSLog(#"scroll tapped");
}
If you do
tap.cancelsTouchesInView = NO;
It will allow button to be pressed. However taps will be detected along with the button press when you press a button. Do avoid this, you will have to subclass UIScrollView and implement the following method –
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
for ( UIView * subview in self.subviews ) {
UIView * hitView = [subview hitTest:point withEvent:event];
if ( hitView )
return hitView;
}
return [super hitTest:point withEvent:event];
}
Implementing the method above pass the touches to the scroll view's subviews.
There is no need to subclass Scrollview. Following code solves the problem easy way. The method gestureRecognizer:shouldReceiveTouch: does the trick.
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesture:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
tap.delegate = self;
tap.cancelsTouchesInView = NO;
[scroll addGestureRecognizer:tap];
[tap release];
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (scroll.superview != nil) {
if ([touch.view isKindOfClass:[UIButton class]])
{
return NO; // ignore the touch
}
}
return YES; // handle the touch
}
- (void)tapGesture:(UIGestureRecognizer*)gesture {
NSLog(#"scroll tapped");
}