How to get UITouch location from UIGestureRecognizer - ios

I want to get the UITouch location of my tap from UIGestureRecognizer, but I can not figure out how to from looking at both the documentation and other SO questions. Can one of you guide me?
- (void)handleTap:(UITapGestureRecognizer *)tapRecognizer
{
CCLOG(#"Single tap");
UITouch *locationOfTap = tapRecognizer; //This doesn't work
CGPoint touchLocation = [_tileMap convertTouchToNodeSpace:locationOfTap];
//convertTouchToNodeSpace requires UITouch
[_cat moveToward:touchLocation];
}
FIXED CODE HERE - THIS ALSO FIXES INVERTED Y AXIS
CGPoint touchLocation = [[CCDirector sharedDirector] convertToGL:[self convertToNodeSpace:[tapRecognizer locationInView:[[CCDirector sharedDirector] openGLView]]]];

You can use the locationInView: method on UIGestureRecognizer. If you pass nil for the view, this method will return the location of the touch in the window.
- (void)handleTap:(UITapGestureRecognizer *)tapRecognizer
{
CGPoint touchPoint = [tapRecognizer locationInView: _tileMap]
}
There is also a helpful delegate method gestureRecognizer:shouldReceiveTouch:. Just make sure to implement and set your tap gesture's delegate to self.
Keep a reference to the gesture recognizer.
#property UITapGestureRecognizer *theTapRecognizer;
Initiailze the gesture recognizer
_theTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: self action: #selector(someMethod:)];
_theTapRecognizer.delegate = self;
[someView addGestureRecognizer: _theTapRecognizer];
Listen for delegate methods.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
CGPoint touchLocation = [_tileMap convertTouchToNodeSpace: touch];
// use your CGPoint
return YES;
}

In Swift:
func handleFrontTap(gestureRecognizer: UITapGestureRecognizer) {
print("tap working")
if gestureRecognizer.state == UIGestureRecognizerState.Recognized
{
print(gestureRecognizer.locationInView(gestureRecognizer.view))
}
}

Try this:
-(void) didMoveToView:(SKView *)view{
oneFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneTapDetected:)];
oneFingerTap.numberOfTapsRequired=1;
oneFingerTap.numberOfTouchesRequired=1;
[view addGestureRecognizer:oneFingerTap];
}
-(void)oneTapDetected:(UITapGestureRecognizer *)recognizer{
NSLog(#"one tap detec");
tapPositionOneFingerTap = [oneFingerTap locationInView:self.view];
NSLog(#"%f, %f",tapPositionOneFingerTap.x,tapPositionOneFingerTap.y);
}
This prints the coordinates of each tap in your console.

Apple Docs say
UIGestureRecognizer
- (NSUInteger)numberOfTouches
The number of UITouch objects in a private array maintained by the receiver.
So you shouldn't access them.
Using the value returned by this method in a loop, you can ask for the location of individual touches using the locationOfTouch:inView: method.

Related

Dragging coordinates with CGPoint

I want to get the coordinates from the user's finger while dragging. I tried this code, but it says the coordinates are always {0, 0},
What's wrong?
- (IBAction)Drag{
UIPanGestureRecognizer *Recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragged)];
[self.view addGestureRecognizer:Recognizer];
}
-(void) dragged{
UITouch *touch ;
CGPoint location = [touch locationInView:touch.view];
NSLog(#"%#", NSStringFromCGPoint (location));
}
I also tried NSLog(#"%.2f %.2f" location.x, location.y); and got the same.
Thanks
It's quite normal, you're using touch without having ever assigned a value to it.
The action for a gesture recognizer takes a parameter, which is the recognizer itself, which in turn has a locationInView: method, so you should use that. Also, you need to check the state of the recognizer. Finally, you probably don't want to add the gesture recognizer when you need it, just add it from the start.
// probably in your viewDidLoad
UIPanGestureRecognizer *Recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(panGestureRecognizerAction:)];
[self.view addGestureRecognizer:Recognizer];
- (void)panGestureRecognizerAction:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan ||
recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint location = [recognizer.state locationInView:touch.view];
NSLog(#"%#", NSStringFromCGPoint (location));
}
}

How to move UIView by longPress on button and then dragging?

I want to move some UIView by button inside this view.
I can it, in that way:
- (void)viewDidLoad
{
[button addTarget:self action:#selector(dragBegan:withEvent:) forControlEvents: UIControlEventTouchDown];
[button addTarget:self action:#selector(dragMoving:withEvent:) forControlEvents: UIControlEventTouchDragInside];
[button addTarget:self action:#selector(dragEnded:withEvent:) forControlEvents: UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
}
.
- (void)dragBegan:(UIControl *)c withEvent:ev {
UITouch *touch = [[ev allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
}
- (void)dragMoving:(UIControl *)c withEvent:ev {
UITouch *touch = [[ev allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
//This is moving view to touchPoint
SimpleView.center = touchPoint;
}
- (void)dragEnded:(UIControl *)c withEvent:ev {
}
How can i move it only then, if I do longPress on that button?
Try using this code. I've used this in a card game i developed. moving cards around using long press gestures. Hope i helps.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(addLongpressGesture:)];
[longPress setDelegate:self];
[YOUR_VIEW addGestureRecognizer:longPress];
- (void)addLongpressGesture:(UILongPressGestureRecognizer *)sender {
UIView *view = sender.view;
CGPoint point = [sender locationInView:view.superview];
if (sender.state == UIGestureRecognizerStateBegan){
// GESTURE STATE BEGAN
}
else if (sender.state == UIGestureRecognizerStateChanged){
//GESTURE STATE CHANGED/ MOVED
CGPoint center = view.center;
center.x += point.x - _priorPoint.x;
center.y += point.y - _priorPoint.y;
view.center = center;
// This is how i drag my views
}
else if (sender.state == UIGestureRecognizerStateEnded){
//GESTURE ENDED
}
I would use this link provided by #Coder404 to detect whether or not the player used a long touch. Then, add an #property BOOL performedLongTouch and set that to YES in the selector passed into the UILongPressGestureRecognizer
Then, in your dragBegan and dragMoving functions, add a check for performedLongTouch and in your dragEnded function, set its value to NO
I know that seem pretty straight forward, but is that what you were looking for?

Is it possible to get the x and y coordinates of a touch?

is it possible to get the x and y coordinates of a touch? If so could someone please provide a very simple example where the coordinates are just logged to the console.
Using touchesBegan Event
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
NSLog(#"Touch x : %f y : %f", touchPoint.x, touchPoint.y);
}
This event is triggered when touch starts.
Using Gesture
Register your UITapGestureRecognizer in viewDidLoad: Method
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureRecognizer:)];
[self.view setUserInteractionEnabled:YES];
[self.view addGestureRecognizer:tapGesture];
}
Setting up the tapGestureRecognizer function
// Tap GestureRecognizer function
- (void)tapGestureRecognizer:(UIGestureRecognizer *)recognizer {
CGPoint tappedPoint = [recognizer locationInView:self.view];
CGFloat xCoordinate = tappedPoint.x;
CGFloat yCoordinate = tappedPoint.y;
NSLog(#"Touch Using UITapGestureRecognizer x : %f y : %f", xCoordinate, yCoordinate);
}
Sample Project
First you need to add a gesture recognizer to the view you want.
UITapGestureRecognizer *myTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myTapRecognizer:)];
[self.myView setUserInteractionEnabled:YES];
[self.myView addGestureRecognizer:myTap];
Then in the gesture recognizer method you make a call to locationInView:
- (void)myTapRecognizer:(UIGestureRecognizer *)recognizer
{
CGPoint tappedPoint = [recognizer locationInView:self.myView];
CGFloat xCoordinate = tappedPoint.x;
CGFloat yCoordinate = tappedPoint.y;
}
You may want to take a look at apple's UIGestureRecognizer Class Reference
Here's a very basic example (place it inside your view controller):
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
NSLog(#"%#", NSStringFromCGPoint(currentPoint));
}
This triggers every time the touch moves. You can also use touchesBegan:withEvent: which triggers when a touch starts, and touchesEnded:withEvent: which triggers when a touch ends (i.e. a finger is lifted).
You can also do this using a UIGestureRecognizer, which in many cases is more practical.

How to get current touch point and previous touch point in UIPanGestureRecognizer method?

I am new to iOS, I am using UIPanGestureRecognizer in my project. In which I have a requirement to get current touch point and previous touch point when I am dragging the view. I am struggling to get these two points.
If I use touchesBegan method Instead of using UIPanGestureRecognizer, I could get these two points by the following code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint touchPoint = [[touches anyObject] locationInView:self];
CGPoint previous=[[touches anyObject]previousLocationInView:self];
}
I need to get these two points in UIPanGestureRecognizer event fire method. How can I achieve this? please guide me.
You can use this:
CGPoint currentlocation = [recognizer locationInView:self.view];
Store previous location by setting current location if not found and adding current location everytime.
previousLocation = [recognizer locationInView:self.view];
When you link an UIPanGestureRecognizer to an IBAction, the action will get called on every change. The gesture recognizer also provides a property called state which indicates if it's the first UIGestureRecognizerStateBegan, the last UIGestureRecognizerStateEnded or just an event between UIGestureRecognizerStateChanged.
To solve your problem, try it like the following:
- (IBAction)panGestureMoveAround:(UIPanGestureRecognizer *)gesture {
if ([gesture state] == UIGestureRecognizerStateBegan) {
myVarToStoreTheBeganPosition = [gesture locationInView:self.view];
} else if ([gesture state] == UIGestureRecognizerStateEnded) {
CGPoint myNewPositionAtTheEnd = [gesture locationInView:self.view];
// and now handle it ;)
}
}
You may also have a look at the method called translationInView:.
If you don't want to store anything you can also do this :
let location = panRecognizer.location(in: self)
let translation = panRecognizer.translation(in: self)
let previousLocation = CGPoint(x: location.x - translation.x, y: location.y - translation.y)
There is a function in UITouch to get the previous touch in the view
(CGPoint)locationInView:(UIView *)view;
(CGPoint)previousLocationInView:(UIView *)view;
You should instantiate your pan gesture recognizer as follows:
UIPanGestureRecognizer* panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
Then you should add panRecognizer to your view:
[aView addGestureRecognizer:panRecognizer];
The - (void)handlePan:(UIPanGestureRecognizer *)recognizer method will be called while the user interacts with the view. In handlePan: you can get the point touched like this:
CGPoint point = [recognizer locationInView:aView];
You can also get the state of the panRecognizer:
if (recognizer.state == UIGestureRecognizerStateBegan) {
//do something
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
//do something else
}

How to get a CGPoint from a tapped location?

I'm working on a graphing calculator app for the iPad, and I wanted to add a feature where a user can tap an area in the graph view to make a text box pop up displaying the coordinate of the point they touched. How can I get a CGPoint from this?
you have two way ...
1.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
}
here,you can get location with point from current view...
2.
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setDelegate:self];
[self.view addGestureRecognizer:tapRecognizer];
here,this code use when you want to do somthing with your perticular object or subview of your mainview
Try This
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
// Get the specific point that was touched
CGPoint point = [touch locationInView:self.view];
NSLog(#"X location: %f", point.x);
NSLog(#"Y Location: %f",point.y);
}
You can use "touchesEnded" if you'd rather see where the user lifted their finger off the screen instead of where they touched down.
Just want to toss in a Swift 4 answer because the API is quite different looking.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = event?.allTouches?.first {
let loc:CGPoint = touch.location(in: touch.view)
//insert your touch based code here
}
}
OR
let tapGR = UITapGestureRecognizer(target: self, action: #selector(tapped))
view.addGestureRecognizer(tapGR)
#objc func tapped(gr:UITapGestureRecognizer) {
let loc:CGPoint = gr.location(in: gr.view)
//insert your touch based code here
}
In both cases loc will contain the point that was touched in the view.
it's probably better and simpler to use a UIGestureRecognizer with the map view instead of trying to subclass it and intercepting touches manually.
Step 1 : First, add the gesture recognizer to the map view:
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(tapGestureHandler:)];
tgr.delegate = self; //also add <UIGestureRecognizerDelegate> to #interface
[mapView addGestureRecognizer:tgr];
Step 2 : Next, implement shouldRecognizeSimultaneouslyWithGestureRecognizer and return YES so your tap gesture recognizer can work at the same time as the map's (otherwise taps on pins won't get handled automatically by the map):
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer
:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Step 3 : Finally, implement the gesture handler:
- (void)tapGestureHandler:(UITapGestureRecognizer *)tgr
{
CGPoint touchPoint = [tgr locationInView:mapView];
CLLocationCoordinate2D touchMapCoordinate
= [mapView convertPoint:touchPoint toCoordinateFromView:mapView];
NSLog(#"tapGestureHandler: touchMapCoordinate = %f,%f",
touchMapCoordinate.latitude, touchMapCoordinate.longitude);
}
If you use an UIGestureRecognizer or UITouch object you can use the locationInView: method to retrieve the CGPoint within the given view the user touched.
func handleFrontTap(gestureRecognizer: UITapGestureRecognizer) {
print("tap working")
if gestureRecognizer.state == UIGestureRecognizerState.Recognized {
`print(gestureRecognizer.locationInView(gestureRecognizer.view))`
}
}

Resources