I have a UIView myView that responds to user taps.
I have added an animated view using:
[myView addSubView:animatedView];
But now the animated view, is blocking the taps, Since both use the same frame
How can I override that easily?
The best way I can see to you to do that is you declare the UITouchGesture in your views, and when you need to disable the touch in the view you can disable:
An example for a tap:
In your .h file you declare it:
UITapGestureRecognizer* tap;
And in your .m file
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[yourView addGestureRecognizer:tap];
And when you need to disable the tap you can simple:
[tap setEnable:NO];
or remove it:
[yourView removeGestureRecognizer:tap];
With that when you need to enable/disable will be easier and also will be easier to you to manage your touchs.
Related
I have an if statement that is bringing up a SVProgressHUD that lets the user know there is an error. I would like to create a touch event programmatically but I am not sure how to define my view when I am using a tableview which was set up in interface builder
this is the code I would like to use
[myView addTarget:self action:#selector(myAction:)forControlEvents:UIControlEventTouchUpInside];
but I am not sure how to create myView when I am using a tableview. What is the best way to handle this?
You can add a UIButton with transparent color and add it to your view.
Then you'll be able to use the following method:
[myButton addTarget:self action:#selector(myAction:)forControlEvents:UIControlEventTouchUpInside];
Add tapGestureRecognizer to the view with target and event to handle the tap event such that when a user click or touches the view it triggers the selector.
UIGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(mySelector:)]
[myView addGestureRecognizer: recognizer];
Then you could add the selector which simply takes the recognizer as the sender;
-(void)mySelector:(UIGestureRecognizer*)gr{
// handling event
}
In my iPad Application I have multiple views on a screen.
What I want to do is apply a double tap Gesture Recognizer to the Navigation Bar. But I had no success, however when the same gesture recognizer applied to that view it works.
Here is the code I am using:
// Create gesture recognizer, notice the selector method
UITapGestureRecognizer *oneFingerTwoTaps =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerTwoTaps)] autorelease];
// Set required taps and number of touches
[oneFingerTwoTaps setNumberOfTapsRequired:2];
[oneFingerTwoTaps setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:oneFingerTwoTaps];
This works on view, but when this is done:
[self.navigationController.navigationBar addGestureRecognizer:oneFingerTwoTaps]
doesn't work.
For anyone else viewing this, here is a much simpler way to do this.
[self.navigationController.view addGestureRecognizer:oneFingerTwoTaps];
For this you need to subclass UINavigationBar, override the init button in it and add your gesture recognizer there.
So say you make a subclass called 'CustomNavigationBar' - in your m file you would have an init method like this:
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
UISwipeGestureRecognizer *swipeRight;
swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(didSwipeRight:)];
[swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[swipeRight setNumberOfTouchesRequired:1];
[swipeRight setEnabled:YES];
[self addGestureRecognizer:swipeRight];
}
return self;
}
Then you need to set the class name of your navigation bar in interface builder to the name of your subclass.
Also it's handy to add a delegate protocol to your navigation bar to listen for methods sent at the end of your gestures. For example - in the case of the above swipe right:
#protocol CustomNavigationbarDelegate <NSObject>
- (void)customNavBarDidFinishSwipeRight;
#end
then in the m file - on the gesture recognised method (whatever you make it) you can trigger this delegate method.
Hope this helps
I have a number of classes and want to add a UIGestureRecognizer to their UIImageViews.
I add one correctly to all the classes. Thing is I duplicate code so that each class is adding the same recognizer. These are local recognizers
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleSingleTap:)];
[singleTap setNumberOfTapsRequired:1];
[background addGestureRecognizer:singleTap];
[singleTap release];
so it should still work for each class.
The problem is that it only works on the first class, not on the others.
background is the UIImageView and is present in every class. So I have multiple backgrounds.
I present each new ModelViewController class, is this maybe what the issue is?
I use the recognizer as follows
- (void) handleSingleTap : (UIGestureRecognizer*) sender
{
//do whatever
}
Each class also implements the
#interface Someclass : UIViewController <UIGestureRecognizerDelegate>
Im not sure why it isnt working though. I have a print out in each handleSingleTap method. and nothing gets printed.
First
Are you adding the same recognizer object to different views? If so that won't work. UIGestureRecognizer objects only detect/track gestures in one view. So make sure you have a different recognizer object for each of your views like:
UITapGestureRecognizer *r1 = [UITapGestureRecognizer alloc] initWithTarget:self action:...];
[view1 addGestureRecognizer:r1];
[r1 release];
UITapGestureRecognizer *r2 = [UITapGestureRecognizer alloc] initWithTarget:self action:...];
[view2 addGestureRecognizer:r2];
[r2 release];
...
Second Make sure the view (in this case UIImageView) is [uiimageview setUserInteractionEnabled:YES];
Third If you are just detecting simple touches then is not necessary to adopt UIGestureRecognizerDelegate protocol, so just delete that protocol from the #interface
Hope it helps
Previously I've used the tap Detecting Window technique to detect taps in a UIWebView, but now I've tried to use gesture recognizers instead. The following code is in the viewDidLoad method of a view controller, which has a single UIWebView. This code compiles fine, but the handleTap method is never called. This seems like it should be simple.
// Configure a gesture recognizer to detect taps in the web view
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap)];
[self.myWebView addGestureRecognizer:singleTap];
[singleTap release];
[super viewDidLoad];
Set your view controller as the recognizer delegate:
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap)];
recognizer.delegate = self;
[self.myWebView addGestureRecognizer:recognizer];
And enable simultaneous gesture recognition (as the UIWebView probably sets a few recognizers itself, yours are skipped) :
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
Since the UIWebView does already handle a lot of touch events, it might be a bit tricky to add your own gesture recognizer.
I don't know if the user has to interact with your web view but you might try to add a UIView on top of the UIWebView and add the gesture recognizer to this view. It should still propagate unrecognized touch events to the underlying web view, thus leaving its interactivity intact.
I want to call an action in two classes (a superview and a full screen subview) when the user single taps the screen. But, when I add a UITapGestureRecognizer to the subview, the one added to the superview is overridden. Is it possible to add a UITapGestureRecognizer to a subview without overriding the UITapGestureRecognizer added to the superview?
If so, how can I do this?
Thanks!
Edit:
From my main viewController "MyToolBerController", I'm adding the subview from another viewController as follows:
PhotoViewController *photoViewController = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
myPhotoView = photoViewController.view;
[self.view addSubview:myPhotoView];
I add the GestureRecognizer in the MyToolBerController like this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTapFrom:)];
[singleTap setNumberOfTapsRequired:1];
singleTap.delegate = self;
[myPhotoView addGestureRecognizer:singleTap];
[singleTap release];
This all works fine, but I need to call a method in the PhotoViewController class when the view is tapped as well as in the MyToolBerController class.
When I add another UITapGestureRecognizer in the photoViewController, it overrides the UITapGestureRecognizer added in the superView.
Gesture recognizers can dispatch multiple actions when the gesture occurs. You can add the subview as another target of the gesture recognizer and only use a single UITapGestureRecognizer instance:
[tapRecognizer addTarget:theSubview action:#selector(whatever:)];
In your gesture recognizer selector method, pass the information along to the subview. There's no need to have multiple gesture recognizers for the same gesture. Something like:
- (IBAction)handleSingleDoubleTap:(UIGestureRecognizer *)sender
{
CGPoint tapPoint = [sender locationInView:sender.view.superview];
UIView *subview = [parentView viewWithTag:100];
[subview doSomethingWithPoint:tapPoint];
}
This of course means that your subview that needs to be notified should be given the tag 100 either in Interface Builder or in code when the view controller gets loaded.
Update based on Jonah's code:
So instead of retaining the view, retain the view controller:
PhotoViewController *photoViewController = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
self.myPhotoViewController = photoViewController;
Which means you need to declare it this way in the MyToolbarController header:
#property (nonatomic, retain) PhotoViewController *myPhotoViewController;
Then, when your gesture selector gets called, pass the message along to the view controller you retained. Something like:
- (IBAction)handleSingleTapFrom:(UIGestureRecognizer *)sender
{
CGPoint tapPoint = [sender locationInView:sender.view.superview];
[myPhotoViewController doSomethingWithPoint:tapPoint];
}
Of course the -doSomethingWithPoint: method is only for example. You can name and create any method you want that takes any parameter you want to pass in your PhotoViewController.
Let me know if you need further clarification.