How to extend tap to handle continuous touches? - ios

I am using the code below to fire a projectile (in a Sprite Kit based game) when the screen is "tapped", this all works fine. However I want to expand this so that handleTap is repeatedly called whilst the user "touches and holds down on the screen" Can anyone point me in the right direction?
// INITIAL SETUP
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setNumberOfTouchesRequired:1];
[view addGestureRecognizer:tapRecognizer];
.
// WHEN TAPPED
- (void)handleTap:(UITapGestureRecognizer *)recognizer {
NSLog(#"%s", __PRETTY_FUNCTION__);
[self setupAndFireProjectile];
}

Use UILongPressGestureRecognizer instead:
// INITIAL SETUP
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleTouch:)];
[view addGestureRecognizer:recognizer];
.
// WHEN TAPPED
- (void)handleTouch:(UILongPressGestureRecognizer *)recognizer {
NSLog(#"%s", __PRETTY_FUNCTION__);
[self setupAndFireProjectile];
}
or use UIResponder's touchesBegan:withEvent: and touchesEnded:withEvent: methods:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// Start shooting
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// End shooting
}

Related

Multiple UITapGestureRecognizer not working on UIScrollView

I want to add multiple UITapGestureRecognizer on UIScrollView but it recognise only one gesture.
I want to add first gesture for touch begin and second one for touch end event.
Following is my code:-
self.tapStartGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesture:)];
self.tapStartGesture.numberOfTapsRequired = 1;
self.tapStartGesture.numberOfTouchesRequired = 1;
[self.tapStartGesture setState:UIGestureRecognizerStateBegan];
[self.scrollView addGestureRecognizer:self.tapStartGesture];
self.tapEndGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesture:)];
self.tapEndGesture.numberOfTapsRequired = 1;
self.tapEndGesture.numberOfTouchesRequired = 1;
[self.scrollView addGestureRecognizer:self.tapEndGesture];
- (void)tapGesture:(UITapGestureRecognizer *)sender {
if(sender==self.tapStartGesture) {
NSLog(#"tapStartGesture");
} else if(sender==self.tapEndGesture) {
NSLog(#"tapEndGesture");
}
}
A tap gesture only has one state - "ended". You can't detect when a tap starts using a tap gesture. As you've seen, attempting to use two tap gestures doesn't accomplish what you want.
You need to implement the UIResponder methods touchesBegan and touchesEnded.
You may also want to see UITapGestureRecognizer - make it work on touch down, not touch up?
.
Issue solved by implement custom gesture.
File:-MyGesture.h
#import <UIKit/UIKit.h>
#interface MyGesture : UIGestureRecognizer
#end
File:-MyGesture.m
#import "MyGesture.h"
#implementation MyGesture
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if (self.state == UIGestureRecognizerStatePossible) {;
self.state = UIGestureRecognizerStateBegan;
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
self.state = UIGestureRecognizerStateEnded;
}
#end
How to Use:-
MyGesture *gesture = [[MyGesture alloc] initWithTarget:self action:#selector(myGesture:)];
[self.scrollView addGestureRecognizer:gesture];
- (void)myGesture:(MyGesture *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
NSLog(#"tapStartGesture");
} else if (sender.state == UIGestureRecognizerStateEnded) {
NSLog(#"tapEndGesture");
}
}

Keyboard Down in IOS

I have some textfield in which when i click it shows me keyboard , but when i click anywhere on the page the keyboard do not disappears . This is my code for resign of first responder. Whats wrong in my code.
Add this code:
-(void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapReceived:)];
[tapGestureRecognizer setDelegate:self];
[self.view addGestureRecognizer:tapGestureRecognizer];
}
-(void)tapReceived:(UITapGestureRecognizer *)tapGestureRecognizer
{
[textField resignFirstResponder];
}
Create iVar for UIGestureRecognizer
UIGestureRecognizer *tapper;
- (void)viewDidLoad
{
[super viewDidLoad];
tapper = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleTap:)];
tapper.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapper];
}
Dismiss what ever is currently editing:
- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
[self.view endEditing:YES];
}
Try this code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[aTextField resignFirstResponder];
}
}
Or
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[self.view endEditing:YES];
}
}
- (void)viewDidLoad {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
-(void)dismissKeyboard {
[yourtextfield resignFirstResponder];
}
Add Tap Gesture on your Top View
you you havn't any subview which may hide your Root view
than only use self.view
if you are using ScrollView than add TapGesture on your ScrollView
-(void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDissmiss:)];
[self.view addGestureRecognizer: tap];
}
Handle Tap Gesture
-(void)tapDissmiss:(UITapGestureRecognizer *)tapGestureRecognizer
{
[self.view endEditing:YES];
}
Create one UITapGestureRecognizer as a class variable.
#interface ViewController() {
UITapGestureRecognizer *tapGesture;
}
- (void)viewDidLoad {
[super viewDidLoad]
tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(dismissKeyboard)];
}
Add gesture on textfield delegates textFieldDidBeginEditing, And remove it on textFieldDidEndEditing.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self.view addGestureRecognizer:_tapGesture];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self.view removeGestureRecognizer:_tapGesture];
}
Implement tap gesture selection
- (void)dismissKeyboard {
[self.view endEditing:YES];
}

How to add UITapGesture and touch both to a single UIImageView in objective c?

when i double tap on image then the image will show in complete view and at the same time i have to drag the image from one place to another in the same view.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
Using the above methods the drag and drop of image is implemented successfully but the UITapGesture is not working now. So, how can I implement both ? ``
By just using UILongPressGrstureRecognizer, it is surprising that it is able to implement tap and drag.
As you just drag first Action will be Tap by default.
You have to:
set the numberOfTapsRequired to 1 to detect the initial tap.
set the minimumDuration something smaller to detect drags quicker without waiting
e.g.:
UILongPressGestureRecognizer *mouseDrag = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleDrag:)];
mouseDrag.numberOfTapsRequired=1;
mouseDrag.minimumPressDuration=0.05;
[clickLeft requireGestureRecognizerToFail:mouseDrag];
to handle the drag, you must determine the state to handle it appropriately as a continuous gesture.
For tap gesture you can simply use
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
[self.imageView addGestureRecognizer:tapGestureRecognizer];
tapGestureRecognizer.delegate = self;
While you tap on image this method invoke
- (void) handleTapFrom: (UITapGestureRecognizer *)recognizer
{
//Code to handle the gesture
}
Did you try to add the simultaneous recognition?
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
For Single Tap in viewDidLoad method,first set the tapGesture Recognizer
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap)];
singleTap.numberOfTapsRequired = 1;
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:singleTap];
Then method
-(void)handleSingleTap
{
NSLog(#"The single tap happened");
}
Touch Events
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if (touch.tapCount == 1) {
NSLog(#"The single tap happened now");
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
NSLog(#"The tap count is - %lu",(unsigned long)touch.tapCount);
if (touch.tapCount == 1)
{
NSLog(#"The single tap Ended now");
}
}

IOS/Objective-C: Detect swipe over UIVIew and button touch up in same location of screen

Hi I have some buttons that trigger action methods.
In addition, I would like the user to be able to swipe left or right over the area with the buttons to show some different buttons
My idea was to add a UIView with a clear background color on top of the buttons so that the user could still see the buttons but could also swipe to the right or left.
However, when the view is over the buttons the buttons no longer work and when it is under the buttons, the swipe is not detected.
In addition to changing the view color to clear, I also tried adjusting the alpha however this seems to work the same way. When alpha of the UIView is zero, swipes are no longer detected and when alpha is greater than zero, the buttons no longer work.
Can anyone suggest a way to do this?
Thanks in advance for any suggestions.
Code I am using for buttons and to detect swipes seems standard. Trying to figure out a way to expose view and buttons at the same time.
Action methods to which buttons are wired:
//.h file
- (IBAction)showIncoming:(id)sender;
- (IBAction)showOutcoming:(id)sender;
/.m file
- (IBAction)showIncoming:(id)sender {
_showIncoming=YES;
_fetchedResultsController=nil;
[self.tableView reloadData];
[self updateInterface];
}
- (IBAction)showOutgoing:(id)sender {
_showIncoming=NO;
_fetchedResultsController=nil;
[self.tableView reloadData];
[self updateInterface];
}
Swipes:
//in viewWillAppear
UISwipeGestureRecognizer *rightRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(rightSwipeHandle:)];
rightRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[rightRecognizer setNumberOfTouchesRequired:1];
rightRecognizer.delegate = self;
[_topView addGestureRecognizer:rightRecognizer];
[_topView setUserInteractionEnabled:YES];
// [rightRecognizer release];
//........towards left Gesture recogniser for swiping.....//
UISwipeGestureRecognizer *leftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(leftSwipeHandle:)];
leftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[leftRecognizer setNumberOfTouchesRequired:1];
leftRecognizer.delegate = self;
[_topView addGestureRecognizer:leftRecognizer];
[_topView setUserInteractionEnabled:YES];
}
- (void)rightSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer
{
//Do moving
NSLog(#"Right Swipe performed");
_showOld=YES;
[self updateInterface];
}
- (void)leftSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer
{
// do moving
NSLog(#"Left Swipe performed");
_showOld=NO;
[self updateInterface];
}
The approach I suggest is listening to a user moving a finger events and firing specified method that would check if user's finger is on your button's view. Sample code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchedViewWithTouches:touches andEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchedViewWithTouches:touches andEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchedViewWithTouches:touches andEvent:event];
}
- (void)didTouchedButton:(NSSet *)touches andEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:touch.view];
UIView *touchedView;
for (UIView *view in self.subviews) {
if(CGRectContainsPoint(view.frame, touchLocation)) {
touchedView = view;
break;
}
}
if (view == self.showIncomingButton) {
[self showIncoming:self.showIncomingButton];
} else if (view == self.showOutcomingButton) {
[self howOutcoming:self.showOutcomingButton];
}
}
Note that you will have to add two outlets for your buttons (if you don't have any). Also, you can get rid off (id)sender in your IBAction calls.

Invoking touchesEnded: when tapped but not swiped

I'm wanting to invoke touchesEnded: method when the user TAPPED on a specific location on the screen but not when a user swipped on the screen. How can I achieve this?
From debugging, it seems that touchesEnded: is called when the user either tapped or swipped. I suppose I can add a local variable to track if the user had swipped like below but I think there is a more robust way of handling this:
BOOL trackSwipe = NO; // Local variable
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
trackSwipe = YES;
// do something
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
if (trackSwipe == YES)
return;
else
{
CGPoint touchPoint = [[touches anyObject] locationInView:self];
// do additional work
}
}
I have also looked into adding UITapGestureRecognizer to invoke the tap selector but this approach doesn't allow me to find the touchPoint which is very important to have.
I appreciate any help on this. Many thanks.
You can try this using a UITapGestureRecognizer
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIGestureRecognizerDelegate>
#end
ViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapMethod:)];
recognizer.numberOfTapsRequired = 1;
recognizer.numberOfTouchesRequired = 1;
recognizer.delegate = self;
[self.view addGestureRecognizer:recognizer];
}
- (void)tapMethod:(UITapGestureRecognizer *)recognizer
{
CGPoint touch = [recognizer locationInView:yourViewHere];
NSLog(#"X: %f Y: %f",touch.x,touch.y);
}
In your viewDidLoad do this:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
Selector method:
-(void)dismissKeyboard{
[self.view endEditing:YES];
}
Using this method you can determine tap gesture.

Resources