I have three UIImageview. I set the action for UIImageview by using tapGesture. I want each UIImageview to have a different action. How can I check that which UIImageview is presently clicked?
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTap setNumberOfTapsRequired:1];
[_imageOne addGestureRecognizer:singleTap];
[_imageTwo addGestureRecognizer:singleTap];
[_imageThree addGestureRecognizer:singleTap];
-(void)singleTapping:(UIGestureRecognizer *)recognizer {
}
You can detect using below code:
-(void)singleTapping:(UITapGestureRecognizer *) recognizer{
if (recognizer.view == _imageOne){
} else if (recognizer.view == _imageTwo) {
}else
{
}
}
A UIGestureRecognizer is to be used with a single view. There is this explicit information in the Apple documentation:
Gesture Recognizers Are Attached to a View
Every gesture recognizer is associated with one view. By contrast, a
view can have multiple gesture recognizers, because a single view
might respond to many different gestures. For a gesture recognizer to
recognize touches that occur in a particular view, you must attach the
gesture recognizer to that view.
Firstly, you can't attach same UITapGestureRecognizer to more than one view.
So, your code will not work and you have to create three UITapGestureRecognizer instances and have to attach it to views like below:
UITapGestureRecognizer *singleTapImg1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg1 setNumberOfTapsRequired:1];
UITapGestureRecognizer *singleTapImg2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg2 setNumberOfTapsRequired:1];
UITapGestureRecognizer *singleTapImg3 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg3 setNumberOfTapsRequired:1];
[_imageOne addGestureRecognizer:singleTapImg1];
[_imageTwo addGestureRecognizer:singleTapImg2];
[_imageThree addGestureRecognizer:singleTapImg3];
Now, you can use below code to get, which imageview clicked and perform action according to that:
-(void)singleTapping:(UIGestureRecognizer *)recognizer {
if (recognizer.view == _imageOne){
//_imageOne tapped
}
else if (recognizer.view == _imageTwo) {
//_imageTwo tapped
}else{
//_imageThree tapped
}
}
Related
I am working on an application which works like a remote control of different devices like Game Console, Set-top Box, etc.
Application contains different type of controls like gesture and buttons to perform events as remote.
Single gesture view contains multiple gesture recognizer as follow:
1 finger Tap using UITapGestureRecognizer
2 finger Tap using UITapGestureRecognizer
1 finger swipe using UISwipeGestureRecognizer
2 finger swipe using UISwipeGestureRecognizer
My requirement is to implement 1 finger Swipe gesture recognizer along with hold event. So, that will continue my swipe action until user will not remove its finger from the view.
I have tried UILongPressGestureRecognizer after UISwipeGestureRecognizer but this didn’t work for me because it is executing along with Swipe movement. And I want this after Swipe end, but finger will not remove.
My code snippet :
-(void) gestureView:(UIView*)viewGesture {
UISwipeGestureRecognizer *swipeGestureSingleRight;
UISwipeGestureRecognizer *swipeGestureSingleLeft;
UISwipeGestureRecognizer *swipeGestureSingleUp;
UISwipeGestureRecognizer *swipeGestureSingleDown;
swipeGestureSingleUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleUp setDelegate:self];
[swipeGestureSingleUp setDirection:(UISwipeGestureRecognizerDirectionUp)];
[swipeGestureSingleUp setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleUp];
swipeGestureSingleDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleDown setDelegate:self];
[swipeGestureSingleDown setDirection:(UISwipeGestureRecognizerDirectionDown)];
[swipeGestureSingleDown setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleDown];
swipeGestureSingleRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleRight setDelegate:self];
[swipeGestureSingleRight setDirection:(UISwipeGestureRecognizerDirectionRight)];
[swipeGestureSingleRight setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleRight];
swipeGestureSingleLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleLeft setDelegate:self];
[swipeGestureSingleLeft setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[swipeGestureSingleLeft setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleLeft];
longPressGestureOnSwipe = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressGesture_Handle:)];
longPressGestureOnSwipe.minimumPressDuration = 0.03;
longPressGestureOnSwipe.delegate = self;
[viewGesture addGestureRecognizer:longPressGestureOnSwipe];
isSwipeEnd = false;
[longPressGestureOnSwipe setEnabled:isSwipeEnd];
}
- (void)swipeGestureSingle_Handle:(UISwipeGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
singleTouchSwipeSenderDirection = sender.direction;
isSwipeEnd = true;
[longPressGestureOnSwipe setEnabled:isSwipeEnd];
}
}
-(void)longPressGesture_Handle:(UILongPressGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
isSwipeEnd = false;
[longPressGestureOnSwipe setEnabled:isSwipeEnd];
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
if (isSwipeEnd) {
[super touchesBegan:touches withEvent:event];
} else {
return;
}
}
Please suggest me correction or solution for my requirement.
Thanks in advance!
I have a tableView with custom cells. I have in one cell a imageView. I want add to this imageView one tapGesture for load a function then I click the imageView. So I have this code into cellForRowAtIndexPath:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
singleTap.numberOfTapsRequired = 1;
[cell.image setUserInteractionEnabled:YES];
[cell.image addGestureRecognizer:singleTap];
and
-(void)tapDetected:(id)sender{
NSLog(#"single Tap on imageview");
}
My problem is that when I scroll the table view this tap is added multiple times and changes into imageView then first click changes.
How can I change add only one time the tapGesture to all cells?
if you have a custom cell you can a function like this:
-(void) addTapGesture:(UITapGestureRecognizer*)tapGesture {
if (self.tapGesture == nil) {
[self.image setUserInteractionEnabled:YES];
[self.image addGestureRecognizer:singleTap];
self.tapGesture = tapGesture
}
}
in this way you are sure to set the tapGesture just once per cell.
Let me know if this can fix your problem
The Problem
Right now, you are adding a new TapGestureRecognizer every time cellForRowAtIndexPath is called, which is every time a cell is about to appear on the screen!
Solution 1: Keep the Old Gesture Recognizer
You can also just check if a cell already contains a gesture recognizer and not add a new one if it does. This will ensure that only one TapGestureRecognizer is applied to each cell:
// Check if the cell already contains a gesture recognizer
// if not, add one!
if (cell.gestureRecognizers.count == 0) {
// Now add the tap gesture recognizer and it will be the only one
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
singleTap.numberOfTapsRequired = 1;
[cell.image setUserInteractionEnabled:YES];
[cell.image addGestureRecognizer:singleTap];
}
Note: You should probably check and make sure the cell contains
exactly the gesture recognizer that you desire- you may want to add
more gesture recognizers to your cells and then you'll have to make
sure it contains the right one!
Solution 2: Remove Gesture Recognizers
Remove all gesture recognizers from the cell before adding the TapGestureRecognizer. This will ensure that only one TapGestureRecognizer is applied to each cell:
// Removes all gesture recognizers in the cell
for (UIGestureRecognizer *recognizer in cell.gestureRecognizers) {
[cell removeGestureRecognizer:recognizer];
}
// Now add the tap gesture recognizer and it will be the only one
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
singleTap.numberOfTapsRequired = 1;
[cell.image setUserInteractionEnabled:YES];
[cell.image addGestureRecognizer:singleTap];
just in you custom cell,do this :(i use swift as example)
class YourCell:UITableViewCell{
//add a variable to track has added a tapgesture to image view
var isAddedTapGesture = false
......
}
in your cellForRowAtIndexPath:
if(cell.isAddedTapGesture == false){
//add the tap gesture to your image
cell.cell.isAddedTapGesture = true
}
In your custom cell header, create a property like
#property (strong, nonatomic) UITapGestureRecognizer *tapGesture;
Add Getter method for the gesture.
- (UITapGestureRecognizer*)tapGesture{
if (!_tapGesture) {
_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
}
return _tapGesture;
}
and inside the awakeFomNib function, Remove and re - add the gesture for the image view like the below.
[self.image removeGestureRecognizer:self.tapGesture];
[self.image addGestureRecognizer:self.tapGesture];
Hope this will be helpfull.
I have a UILabel and when i double tap on it ,it should assign value of Label to the other view's UITextView otherwise next view's textview should be empty.
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setDelegate:self];
[holderView addGestureRecognizer:tapRecognizer];
tapRecognizer = nil;
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(LaunchText)];
[doubleTapRecognizer setNumberOfTapsRequired:2];
[doubleTapRecognizer setDelegate:self];
[holderView addGestureRecognizer:doubleTapRecognizer];
holderView.userInteractionEnabled=YES;
[tapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
/*n=[SingleTon getInstance];
n.Name=textLabel.text;*/
if (doubleTapRecognizer.numberOfTapsRequired==2) {
n.Name=#"hi";
}
/* if (doubleTapRecognizer.numberOfTapsRequired==2) {
n.Name=textLabel.text;
}*/
else{
//n.Name=textLabel.text;
n.Name=#"hellow";
}
-(void) LaunchText
{
[self performSegueWithIdentifier:#"textAdd" sender:self];
}
I am always getting if condition, else part never runs, What is the issue with my code?
Please try below code.
//first add single tap
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleT:)];
[tapRecognizer setNumberOfTapsRequired:1];
[holderView addGestureRecognizer:tapRecognizer];
//now add double tap
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleT:)];
[doubleTapRecognizer setNumberOfTapsRequired:2];
[holderView addGestureRecognizer:doubleTapRecognizer];
holderView.userInteractionEnabled=YES;
[tapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
Now Implement Single Tap and Double Tap Method
-(void)singleT:(UITapGestureRecognizer *)gest
{
NSLog(#"Single");
}
-(void)doubleT:(UITapGestureRecognizer *)gest
{
NSLog(#"double");
}
Maybe this will help you.
doubleTapRecognizer.numberOfTapsRequired==2 is the value you set to how many times the user has to tap to set off the gesture recognizer. it you want to allow for single and double taps you can keep a count on the gesture recognizer target and see how many times they've tapped over a giving time, like 0.2 secs or whatever time you want. I'm not 100% sure but you could also try to add two gestures to the label one for numberOfTapsRequired = 1 and numberOfTapsRequired = 2 and have them both perform different functions. Again i'm not sure on the two recognizers but you could give it a try and try the other method otherwise.
I am trying to use this code for a tap gesture recognizer, it works fine when number of taps required is set to 2, but when I set the number of taps required to 1 it stop functioning. I appreciate any help in getting this to work.
UITapGestureRecognizer *doubleTap =
[[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(tapDetected:)];
[doubleTap setNumberOfTapsRequired : 1];
[doubleTap setDelaysTouchesBegan : YES];
[self.view addGestureRecognizer:doubleTap];
You try this:-
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget: self action:#selector(tapDetected:)];
singleTap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:singleTap];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget: self action:#selector(tapDetected:)];
doubleTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:doubleTap];
[singleTap requireGestureRecognizerToFail:doubleTap];
This works for me.
If You only want the receiver to respond to one/first touch then setDelaysTouchesBegan:NO Since this is used for processing touches in UITouchPhaseBegan so it is analyzed and is prevented from being delivered. Property discussion from documentation:
When the value of this property is NO (the default), views analyze touch events in UITouchPhaseBegan and UITouchPhaseMoved in parallel with the receiver. When the value of the property is YES, the window suspends delivery of touch objects in the UITouchPhaseBegan phase to the view. If the gesture recognizer subsequently recognizes its gesture, these touch objects are discarded. If the gesture recognizer, however, does not recognize its gesture, the window delivers these objects to the view in a touchesBegan:withEvent: message (and possibly a follow-up touchesMoved:withEvent: message to inform it of the touches’ current locations). Set this property to YES to prevent views from processing any touches in the UITouchPhaseBegan phase that may be recognized as part of this gesture.
It looks to me like you are simply failing to set the delegate of your GestureRecognizer. Are you sure the double tap was firing successfully? When I placed your code into my project I see the same behavior but setting the delegate properly and using shouldRecognizeSimultaneouslyWithGestureRecognizer causes it to recognize the single tap properly.
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapDetected:)];
[doubleTap setDelegate:self];
[doubleTap setNumberOfTapsRequired : 1];
[doubleTap setDelaysTouchesBegan : YES];
[picker addGestureRecognizer:doubleTap];
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([gestureRecognizer isKindOfClass:UITapGestureRecognizer.class] &&
[otherGestureRecognizer isKindOfClass:UITapGestureRecognizer.class])
{
return YES;
}
else
{
return NO;
}
}
I have a view controller with 3 UIWebViews, all with the same frame overlaying each other. I use three buttons to switch between them (similar to a segment control). I want to attach a tap gesture recognizer to the webview so that tapping each webview leads to a new controller. However, only the UITapGestureRecognizer for the first webview fires. Can anyone tell me how to get the other two gesture recognizers to fire? This is my code:
- (IBAction)changeWebView:(id)sender
{
UIButton *button = (UIButton *)sender;
switch (button.tag) {
case 0:
{
[self.view bringSubviewToFront:WebView1];
for (UITapGestureRecognizer *recognizer in WebView2.gestureRecognizers) {
[WebView2 removeGestureRecognizer:recognizer];
}
for (UITapGestureRecognizer *recognizer in WebView3.gestureRecognizers) {
[WebView3 removeGestureRecognizer:recognizer];
}
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showFullScreen1)];
tapGestureRecognizer.delegate = self;
[WebView1 addGestureRecognizer:tapGestureRecognizer];
}
break;
case 1:
{
[self.view bringSubviewToFront:WebView2];
for (UITapGestureRecognizer *recognizer in WebView1.gestureRecognizers) {
[WebView1 removeGestureRecognizer:recognizer];
}
for (UITapGestureRecognizer *recognizer in WebView3.gestureRecognizers) {
[WebView3 removeGestureRecognizer:recognizer];
}
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showFullScreen2)];
tapGestureRecognizer.delegate = self;
[WebView2 addGestureRecognizer:tapGestureRecognizer];
}
break;
case 2:
{
[self.view bringSubviewToFront:WebView3];
for (UITapGestureRecognizer *recognizer in WebView1.gestureRecognizers) {
[WebView1 removeGestureRecognizer:recognizer];
}
for (UITapGestureRecognizer *recognizer in WebView2.gestureRecognizers) {
[WebView2 removeGestureRecognizer:recognizer];
}
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showFullScreen3)];
tapGestureRecognizer.delegate = self;
[WebView3 addGestureRecognizer:tapGestureRecognizer];
}
break;
default:
break;
}
}
This sounds like a design issue. Why don't you only have one one UIView and render the correct content depending on what button was pressed. You can then have only one gesture recognizer that will load the proper controller (or perform the correct segue) also depending on the button.
Add UITapGestureRecognizer to a a view and add all 3 UIWebview as a subview on them.Than whenever you detect UITapGestureRecognizer to be tapped get the tag from segmentedController or button whatever you are using and find which one was tapped.
Don't add UITapGestureRecognizer and remove it again and again.