I have a button that behaves in one way when user taps on it and another when user double taps on it. In case the user double taps the button, i don't want the single tap behavior to happen.
How can i prevent the call to the touch down event in case double tap was recognized?
You can use Target-action; For UIControlEvents, you can use "UIControlEventTouchDown" and "UIControlEventTouchDownRepeat" like this:
UIButton * button = [UIButton buttonWithType:UIButtonTypeContactAdd];
button.frame = CGRectMake(150, 200, 50, 50);
[button addTarget:self action:#selector(buttonSingleTap:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(buttonMutipleTap:) forControlEvents:UIControlEventTouchDownRepeat];
[self.view addSubview:button];
- (void)buttonSingleTap:(UIButton *)btn{
[self performSelector:#selector(buttonAction:) withObject:btn afterDelay:0.5];
}
- (void)buttonAction:(UIButton *)sender{
NSLog(#"single tap");
}
- (void)buttonMutipleTap:(UIButton *)btn{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(buttonAction:) object:btn];
NSLog(#"mutiple tap!");
}
But there will be 0.5sec to delay!
As I understand you want different behavior on the same button,So simply apply two different tap gesture.The below code may help you.
UIButton *btn1=[[UIButton alloc]init]; //your button
//Two diff method call for two diff behaviour
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapEvent:)];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapEvent:)];
//specify the number of tapping event require to execute code.
singleTap.numberOfTapsRequired = 1;
doubleTap.numberOfTapsRequired = 2;
[singleTap requireGestureRecognizerToFail:DoubleTap];
//Apply multiple tap gesture to your button
[btn1 addGestureRecognizer:singleTap];
[btn1 addGestureRecognizer:doubleTap];
Related
Good evening, I'm trying to create a grid of buttons, like in the following code.
I'd like to add t a TapGesture and a LongPress Gesture to each of the buttons; how do I do it?
I know this is a way to do it...
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(longPress:)];
longPress.minimumPressDuration = 3;
//[self.griglia[1][1] addGestureRecognizer:longPress];
If I do so, it says "Property "griglia" not found on object of type Gioco
Gioco.m/Gioco.h is my class
and UIButton* griglia[9][9]; is my button grid
Could you correct the following code?
for(int i=0, y=212, p=0; i<9; i++)
{
for(int k=0, x=37; k<9; k++)
{
griglia[i][k] = [UIButton buttonWithType:(UIButtonTypeCustom)];
//[griglia[i][k] addTarget:self action:(#selector(click)) forControlEvents: UIControlEventTouchDown];
[griglia[i][k] setTag: 0];
if(i==posizioni[0][p] && k==posizioni[1][p])
{
numero=[NSString stringWithFormat:#"%d", matrice[i] [k]];
[griglia[i][k] setTitle: numero forState: UIControlStateNormal];
[griglia[i][k] setEnabled:NO]; //Numeri non modificabili
[griglia[i][k] setTag: matrice[i][k]];
}
[griglia[i][k] setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
griglia[i][k].frame=CGRectMake(x, y, 27, 27);
[self.view addSubview:griglia[i][k]];
if(k==2 || k==5)
x=37+3+k*34;
else
x=37+k*34;
}
if(y==2 || y==5)
y=212+4+i*34;
else
y=212+i*34;
}
This is not making sense.
You are creating a UILongPressGestureRecognizer
and then
//[griglia[i][k] addTarget:self action:(#selector(click))
forControlEvents: UIControlEventTouchDown];
Those are two different things.
A touchdown is a gesture, but very different than the long press.
I would suggest you try to add a gesture recognizer, and not add a touchdown event to your buttons.
Or...
take a look at this answer instead:
Adding Tap Gesture on UIImage
My project has UIButtons which are taking up to 1 second to execute the block of code.
I have buttons in other projects working fine, but for some odd reason, this project has an annoying delay.
The buttons are dailer numbers, so they need to be pressed quickly:
Heres an example of one:
- (IBAction)phonePressed:(id)sender {
UITapGestureRecognizer *backspaceGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(backspace)];
UIButton *one = [[UIButton alloc] initWithFrame:CGRectMake(menuShadowLayer2.frame.origin.x+10, menuShadowLayer2.frame.origin.y+10, 80, 80)];
one.layer.cornerRadius = 40;
one.layer.borderColor = [UIColor lightGrayColor].CGColor;
one.layer.borderWidth = 1;
[one setBackgroundColor:[UIColor colorWithRed:0/255.0f green:0/255.0f blue:0/255.0f alpha:0.3]];
[one setTitle:#"1" forState:UIControlStateNormal];
[one.titleLabel setTextAlignment:NSTextAlignmentCenter];
[one setTitleColor:[UIColor whiteColor]forState:UIControlStateNormal];
[one.titleLabel setFont:[UIFont fontWithName:#"STHeitiSC-Light" size:50]];
[container addSubview:one];
[one addGestureRecognizer:tap1];
...
- (void)dailed1 {
numberDailed.text = [numberDailed.text stringByAppendingString:#"1"];
NSLog(#"1");
}
Here is another button using UIControlEventTouchUpInside, which is just as slow if not slower.
UIButton *cancel = [[UIButton alloc] initWithFrame:CGRectMake(numberDailed.frame.origin.x, numberDailed.frame.origin.y+200, numberDailed.frame.size.width+40, 110)];
cancel.layer.cornerRadius = 15;
[cancel setImage:[UIImage imageNamed:#"cancel.png"] forState:UIControlStateNormal];
cancel.clipsToBounds = YES;
[container addSubview:cancel];
[cancel addTarget:self
action:#selector(clearNumber:)
forControlEvents:UIControlEventTouchDown];
...
-(IBAction)clearNumber:(id)sender{
[numberDailed setText:#""];
}
I have used a UITapGestureRecognizer as using the Button UIControlEventTouchUpInside or TouchDown was even slower.
When pressing this button (one), I have to wait around half a second to a second before tapping again. This obviously creates frustration when your entering a number and half of the numbers haven't been added to the string.
I have set the UIScrollView to delaysContentTouches = NO;
The button highlights immediately. It simply wont execute the code straight away.
I have used button one as an example, but this applies to ALL UIButtons in my project.
Thoughts?
Where you are using the gesture,
[one addGestureRecognizer:tap1];
instead, you should use the button action
[one addTarget:self action: #selector(dailed1:)];
Couple things. Firstly, create your button like so:
UIButton *numberButton = [UIButton buttonWithType:UIButtonTypeCustom];
numberButton.frame = CGRectMake(...);
Secondly, as others have pointed out, you do not need any gestures, but should attach an action/target to the button:
[numberButton addTarget:self action:#selector(numberDialled:) forControlEvents: UIControlEventTouchUpInside];
Thirdly, create your IBAction:
- (IBAction) numberDialled:(id)sender
The problem turned out to be with the MapBox API(Not Recommended) in my project, removing this sped everything up. All code was fine, have gone back to performing selector and removed the gestures.
I know how to create popovers if my button added to story board, but how can I create popover if my button created via code.
UIButtonS *button = [UIButtonS buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(siteButtonPressed:)forControlEvents:UIControlEventTouchUpInside];
[button setTitle:string1 forState:UIControlStateNormal];
button.frame = CGRectMake(XLocatioan, YLocation, 90, 30);
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongPress:)];
longPress.minimumPressDuration = 1.0;
[button addGestureRecognizer:longPress];
[self.view addSubview:button];
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
}
else if (sender.state == UIGestureRecognizerStateBegan){
//create popover for button
}
}
You are already doing it right, but you are overthinking. There is no need to check the state of the gesture recognizer. If the target function has been triggered, it means that the user has done a long press. Also, note that not all of the values of the property state may be supported. As the documentation says: Some of these states are not applicable to discrete gestures.
So your code should look like this (unless you want to implement dragging or something similar):
UIButtonS *button = [UIButtonS buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(siteButtonPressed:)forControlEvents:UIControlEventTouchUpInside];
[button setTitle:string1 forState:UIControlStateNormal];
button.frame = CGRectMake(XLocatioan, YLocation, 90, 30);
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongPress:)];
longPress.minimumPressDuration = 1.0;
[button addGestureRecognizer:longPress];
[self.view addSubview:button];
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
//create popover for button
}
If your target is iOS 6+ you should use a UIPopoverController to create the popover, otherwise use UIAlertView.
I have added an ui button to a disclouser button
And implemented selector method
but the action selector doesn't respond to the button why and what to do
//To add a discloser button to show route map
UIButton *detailBtn=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.leftCalloutAccessoryView=detailBtn;
[detailBtn addTarget:self action:#selector(showRoute:) forControlEvents:UIControlEventTouchUpInside];
DisplayMap *ann=(DisplayMap *)annotation;
detailBtn.tag = ann.detailButtonTag;
UIButton *btnOnPopup=[[UIButton alloc] initWithFrame:CGRectMake(- 207, -6, 300, 43)];
btnOnPopup.backgroundColor = [UIColor whiteColor];
[btnOnPopup addTarget:self action:#selector(showRoute2:) forControlEvents:UIControlEventTouchUpInside];
btnOnPopup.tag = ann.detailButtonTag;
btnOnPopup.userInteractionEnabled = YES;
[detailBtn insertSubview:btnOnPopup aboveSubview:detailBtn];
the selector
[btnOnPopup addTarget:self action:#selector(showRoute2:) forControlEvents:UIControlEventTouchUpInside];
(Second button btnOnPopup) is not working.
Your btnOnPopup is out of detailBtn's bounds so touches won't even get to it. Adding a button to a button is not really a great practice anyway. Adding it to a button's superview might be a little bit better (and will make your touches work, but you might need to adjust frame)
[detailBtn.superview insertSubview:btnOnPopup aboveSubview:detailBtn];
Add view and tap gesture recognizer instead of button:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureHandler:)];
[singleTap setNumberOfTapsRequired:1];
[view addGestureRecognizer:singleTap];
...
[detailBtn addSubview:view];
...
- (void)tapGestureHandler:(UIGestureRecognizer *)gestureRecognizer
{
// your code for tap handler is here
}
How can I put a info button in the imageview frame reserved in uitableViewcell?
Thanks in advance!
All you need to do is create the button and add it to the cell:
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton setFrame:CGRectMake(10,10,infoButton.frame.size.width, infoButton.frame.size.height)];
[infoButton addTarget:self action:#selector(infoButtonTapped) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:infoButton];
Edit---
As you want to use the imageView property of the cell, you are required to provide your own image and you need to set a gesture recogniser so that you know when the imageView has been tapped.
[cell.imageView setImage:[UIImage imageNamed:#"info-button.png"]];
[cell.imageView setUserInteractionEnabled:YES];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(infoImageTapped:)];
[tap setNumberOfTapsRequired:1];
[cell.imageView setGestureRecognizers:[NSArray arrayWithObject:tap]];
[tap release];
- (void) infoImageTapped:(UITapGestureRecognizer *) tap {
//show info view.
}