I am faceing a small prob. Please help me.
When i press and hold on my view my function called 2-3 times and some times after releasing hold the long press function again called.
In View did load
-(void)viewdidload
{
UILongPressGestureRecognizer *longPressGesture =
[[[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(longPress:)] autorelease];
[self.view addGestureRecognizer:longPressGesture];
[self.view release];
}
-(void)longPress:(UILongPressGestureRecognizer *)sender
{
NSLog(#"******Long Press*******");
}
Long press printed many times.
You probably want to just return from longPress if the gesture has not ended. Put this code right at the top of longPress:
if (sender.state != UIGestureRecognizerStateEnded)
{
return;
}
Related
Giving thanks in advance, I would like to share the strange behaviour of UILongPressGestureRecognizer.
UIView *v = [UIView alloc] initWithFrame:CGRectMake(0,0,20,20)];
UILongPressGestureRecognizer *longpressGesture1 = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[v addGestureRecognizer:longpressGesture1];
and here the delegate to handle the gesture recogniser.
-(IBAction)tapped:(UILongPressGestureRecognizer *) gesture
{
switch ([gesture state]) {
case UIGestureRecognizerStateBegan:
{
NSLog(#"Long Tap detacted.");
}
break;
case UIGestureRecognizerStateChanged:
{
NSLog(#"UIGestureRecognizerStateChanged");
}
break;
case UIGestureRecognizerStateEnded:
{
NSLog(#"Long Tap ended.");
}
break;
}
}
This piece of code is working perfectly as expected in iOS 4 and 5, but in ios 6 with retina display when we perform the long tap, UIGestureRecognizerStateBegan is being called twice for a single long tap resulting in a application crash.
Any help is greatly welcome.
UILongPressGestureRecognizer is a continuous event recognizer. You have to look at the state to see if this is the start, middle or end of the event and act accordingly.
Its calling two times because you are pressing and removing your finger.
First call is indicating you that there is an Long tap detected i.e. UIGestureRecognizerStateBegan
Second call is indicating you that there is end of that tap i.e. UIGestureRecognizerStateBegan
There are three state of tap
UIGestureRecognizerStateBegan
UIGestureRecognizerStateChanged
UIGestureRecognizerStateEnded
If you will drag your finger then it will called multiple time that will indicate that there is some changes in its state.
Follow UILongPressGestureRecognizer Class Reference for more
I have two labels in two different positions, when both labels are tapped at the same time i want another label to show a success message.
How do I accomplish this? I can recognize a single tap or double tap with one or more finger touches but this is a different scenario. Please help. I tried this, but it does not work.
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapRecognizer.numberOfTapsRequired = 1;
tapRecognizer.numberOfTouchesRequired = 2;
tapRecognizer.delegate = self;
[self.view addGestureRecognizer:tapRecognizer];
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view == tap2 && touch.view == tap1)
{
result.text = #"success";
}
return YES;
}
Thanks in advance.
What you're trying to detect isn't really a single gesture.
I'd suggest adding a tap gesture recogniser to each button. The handler would:
Store the time of the tap (at the moment that the handler is called)
Compare this time with the time that the other button was last
tapped. If the times are very similar (perhaps 0.25 secs apart),
consider that they've both been tapped simultaneously and react
accordingly.
Play with the time interval on a real device to find the ideal amount.
UPDATE:
A code snippet that obviously hasn't been tested in any way:
- (void)handleButton1Tap:(UITapGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateEnded)
{
self.button1TapTime = CACurrentMediaTime();
[self testForSimultaneousTap];
}
}
- (void)handleButton2Tap:(UITapGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateEnded)
{
self.button2TapTime = CACurrentMediaTime();
[self testForSimultaneousTap];
}
}
- (void)testForSimultaneousTap
{
if (fabs(self.button1TapTime - self.button2TapTime) <= 0.2)
{
// Do stuff
}
}
where self.button1TapTime and self.button2TapTime are member variables (doubles).
Tim
Formally I had accepted termes's answer first and that worked too, but I have found a more simpler solution to this process. There is no need for two gesture recognizers, it is achievable with a simple tap gesture recognizer with number of touches count to two. Here is the code:
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapRecognizer.numberOfTapsRequired = 1;
tapRecognizer.numberOfTouchesRequired = 2;
tapRecognizer.delegate = self;
[self addGestureRecognizer:tapRecognizer];
Now, in the handle tap method we can easily get the two touch points by "locationOfTouch:inView:", a instance method of UIGestureRecognizer class. So in the handleTap: method we need to check if the two touch points are in the desired location. Here is the code:
-(void)handleTap:(UITapGestureRecognizer*)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded)
{
CGPoint point1 = [recognizer locationOfTouch:0 self];
CGPoint point2 = [recognizer locationOfTouch:1 self];
if ([self validateTapIn:point1 and:point2])
{
resultLabel.text = #"success";
}
}
}
-(BOOL)validateTapIn:(CGPoint)point1 and:(CGPoint)point2
{
return
(CGRectContainsPoint(label1.frame, point1) && CGRectContainsPoint(label2.frame,:point2)) ||
(CGRectContainsPoint(label1.frame, point2) && CGRectContainsPoint(label2.frame, point1));
}
I have a table view, and I use UILongPressGestureRecognizer on table view cell to show a context menu over the cell to allow user perform some extra functionality. Everything is work well in iOS 5.1, but when I test in iOS 5 and 4.3, the event is not fired.
Does anyone know how to solve this problem please help me, thanks in advance.
Below is my code:
in tableViewCell.h: add UIGestureRecognizerDelegate
in tableViewCell.m
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
longPressRecognizer.minimumPressDuration = 1.5;
longPressRecognizer.numberOfTouchesRequired = 1;
longPressRecognizer.numberOfTapsRequired = 0;
longPressRecognizer.delegate = self;
[self addGestureRecognizer:longPressRecognizer];
[longPressRecognizer release];
// Method to handle event
- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
{
// Do something.
}
}
After spending 1.5 days on this issue, I discover that somehow the tableView receives long press event but tableViewCell does not on iOS 5/4.3 . So I fixed this issue by adding UILongPressGuestureRecognizer to tableView then in the long press event handler then call tableViewCell to show the context menu, and it works.
I met this problem too. I found that long press gesture recognizer works fine only when 'delegate' property is 'NULL'. So just try to remove this line.
longPressRecognizer.delegate = self;
guys,
I have added two UILongPressGestureRecognizer. What I want is when two buttons are pressed down for 0.3 second, fire up "shortPressHandler". If user keeps pressing these two buttons for another 1.2 second, fire up "longPressHandler". Now I only get shortPressHandler fired up and the longPressHandler was never fired. I think it might because the shortPressGesture is recognized first and longPressGesture never gets a chance. Can anyone show me how to achieve what I want? Thanks in advance.
UILongPressGestureRecognizer *longPressGesture =[[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressHandler:)] autorelease];
longPressGesture.numberOfTouchesRequired = 2;
longPressGesture.minimumPressDuration = 1.5;
longPressGesture.allowableMovement = 10;
longPressGesture.cancelsTouchesInView = NO;
longPressGesture.enabled = true;
[self.view addGestureRecognizer:longPressGesture];
UILongPressGestureRecognizer *shortPressGesture =[[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(shortPressHandler:)] autorelease];
shortPressGesture.numberOfTouchesRequired = 2;
shortPressGesture.minimumPressDuration = 0.3;
shortPressGesture.allowableMovement = 10;
shortPressGesture.cancelsTouchesInView = NO;
shortPressGesture.enabled = true;
[self.view addGestureRecognizer:shortPressGesture];
Insert this line before adding shortPressGesture:
[shortPressGesture requireGestureRecognizerToFail:longPressGesture];
Note: shortGesture will not get called immediately after 0.3 seconds of holding but when the tap is released if it was between 0.3 seconds and 1.2 seconds long. If the tap is longer than 1.2 s (you have 1.5s in your code which is probably a typo) only longPressGesture will fire up.
EDIT:
However, if you want your event handlers both to fire (in an event of long press), you should do this:
Your UIView of should implement the <UIGestureRecognizerDelegate> in .h file.
In .m file you add this method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Now instead of adding the line:
[shortPressGesture requireGestureRecognizerToFail:longPressGesture];
You add this two lines:
shortPressGesture.delegate = self;
longPressGesture.delegate = self;
NOTE: if you have any other UIGestureRecognisers linked to your UIVIew you will have to add some checking in shouldRecognizeSimultaneouslyWithGestureRecognizer:, otherwise you can simply return YES.
What I am trying to achieve is showing a view during a couple of seconds without user intervention. Is the same effect as the ringer volume view that appears when pressing the volume controls on iphone:
I have a scroll view with an image, taping in the image, sound begin to play, another tap and it pauses. I would like to implement the above effect just to inform of the action (showing a play/pause images).
I hope that I have explained the problem perfectly.
Many thanks for your help.
Regards
Javi
Assume you have some class inherited from UIViewController. You can use the code below:
const int myViewTag = 10001;
const int myInterval = 1; // define the time you want your view to be visible
- (void)someAction {
//this could be your `IBAction` implementation
[self showMyView];
[NSTimer scheduledTimerWithTimeInterval:myInterval
target:self
selector:#selector(hideMyView)
userInfo:nil
repeats:NO];
}
- (void) showMyView {
//you can also use here a view that was declared as instance var
UIView *myView = [[[UIView alloc] initWithFrame:CGRectMake(100, 100, 120, 120)] autorelease];
myView.tag = myViewTag;
[self.view addSubview:myView];
}
- (void) hideMyView {
//this is a selector that called automatically after time interval finished
[[self.view viewWithTag:myViewTag] removeFromSuperview];
}
You can also add some animations here but this is another question :)