Get the start point and end point of the UIPanGestureRecognizer in Swift
For your case, you might want to include the code inside my function into your IBAction for the panGesture. Here I've created a view, but otherwise you would just be referring to self.view
instead of view
.
var view = UIView()
func panGestureMoveAround(gesture: UIPanGestureRecognizer) {
var locationOfBeganTap: CGPoint
var locationOfEndTap: CGPoint
if gesture.state == UIGestureRecognizerState.Began {
locationOfBeganTap = gesture.locationInView(view)
} else if gesture.state == UIGestureRecognizerState.Ended {
locationOfEndTap = gesture.locationInView(view)
}
}
How do I capture the point initially tapped in a UIPanGestureRecognizer?
Late to the party, but I notice that nothing above actually answers the question, and there is in fact a way to do this. You must subclass UIPanGestureRecognizer and include:
#import <UIKit/UIGestureRecognizerSubclass.h>
either in the Objective-C file in which you write the class or in your Swift bridging header. This will allow you to override the touchesBegan:withEvent method as follows:
class SomeCoolPanGestureRecognizer: UIPanGestureRecognizer {
private var initialTouchLocation: CGPoint!
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
super.touchesBegan(touches, withEvent: event)
initialTouchLocation = touches.first!.locationInView(view)
}
}
Then your property initialTouchLocation will contain the information you seek. Of course in my example I make the assumption that the first touch in the set of touches is the one of interest, which makes sense if you have a maximumNumberOfTouches of 1. You may want to use more sophistication in finding the touch of interest.
Edit: Swift 5
import UIKit.UIGestureRecognizerSubclass
class InitialPanGestureRecognizer: UIPanGestureRecognizer {
private var initialTouchLocation: CGPoint!
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
initialTouchLocation = touches.first!.location(in: view)
}
}
How to access the initial point of a Pan Gesture in it's .Ended state
The way you are doing this doesn’t work. Instead, calculate it all at the end:
func handleTestViewTap (panRecognizer: UIPanGestureRecognizer){
if panRecognizer.state == UIGestureRecognizerState.Ended {
print("locationOfBeganTap -> (.\(touch.locationInView(view).x - touch.translationInView(view).x), .\(touch.locationInView(view).y - touch.translationInView(view).y))")
print("location in ENDED State -> .\(touch.locationInView(view))")
}
}
Draw a rectangle the starting point and follow my movement to end the gesture in Swift
You need to create a subclass of UIView call it something like RectView and like this:
@IBDesignable
class RectView: UIView {
@IBInspectable var startPoint:CGPoint?{
didSet{
self.setNeedsDisplay()
}
}
@IBInspectable var endPoint:CGPoint?{
didSet{
self.setNeedsDisplay()
}
}
override func drawRect(rect: CGRect) {
if (startPoint != nil && endPoint != nil){
let path:UIBezierPath = UIBezierPath(rect: CGRectMake(min(startPoint!.x, endPoint!.x),
min(startPoint!.y, endPoint!.y),
fabs(startPoint!.x - endPoint!.x),
fabs(startPoint!.y - endPoint!.y)))
path.stroke()
}
}
}
Then in your view controller you can say something like:
@IBAction func panGestureMoveAround(sender: UIPanGestureRecognizer) {
var locationOfBeganTap: CGPoint
var locationOfEndTap: CGPoint
if sender.state == UIGestureRecognizerState.Began {
locationOfBeganTap = sender.locationInView(rectView)
rectView.startPoint = locationOfBeganTap
rectView.endPoint = locationOfBeganTap
} else if sender.state == UIGestureRecognizerState.Ended {
locationOfEndTap = sender.locationInView(rectView)
rectView.endPoint = sender.locationInView(rectView)
} else{
rectView.endPoint = sender.locationInView(rectView)
}
}
Swift 5 version
class RectView: UIView {
var startPoint: CGPoint? {
didSet {
setNeedsDisplay()
}
}
var endPoint: CGPoint? {
didSet {
setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
guard let startPoint = startPoint, let endPoint = endPoint else {
return
}
let path = UIBezierPath(
rect: CGRect(
x: min(startPoint.x, endPoint.x),
y: min(startPoint.y, endPoint.y),
width: abs(startPoint.x - endPoint.x),
height: abs(startPoint.y - endPoint.y)
)
)
path.stroke()
}
}
@objc func panGestureMoveAround(_ sender: UIPanGestureRecognizer) {
var locationOfBeganTap: CGPoint
switch sender.state {
case .began:
locationOfBeganTap = sender.location(in: rectView)
rectView.startPoint = locationOfBeganTap
rectView.endPoint = locationOfBeganTap
case .changed:
rectView.endPoint = sender.location(in: rectView)
case .ended:
rectView.endPoint = sender.location(in: rectView)
default:
break
}
}
How to get current touch point and previous touch point in UIPanGestureRecognizer method?
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];
UIPanGestureRecognizer get the length between start and stop
The problem is that handlePanRecognizer()
is called every time the gesture is updated, so when the gesture ends, you don't have the startLocation because it was set in another call of the handler method.
You should store last location as an optional property:
var startPanLocation: CGPoint?
Now set it in .began
case and use it to calculate the distance in .ended
case:
func handlePanRecognizer(panRecognizer: UIPanGestureRecognizer) {
let currentLocation = panRecognizer.location(in: self.newEffectView)
switch panRecognizer.state {
case .began:
startPanLocation = currentLocation
case .ended:
let dx = currentLocation.x - startPanLocation.x;
let dy = currentLocation.y - startPanLocation.y;
let distance = sqrt(dx*dx + dy*dy );
startPanLocation = nil
default: break
}
}
Btw, you cannot use the variable if it was defined but not initialized:
let startLocation : CGPoint //defined
let startLocation = CGPoint.zero //initialized
Get original touch location from UIPanGestureRecognizer
You should be able to set the delegate
for the gesture recogniser and implement
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
to get the initial touch.
Detecting Pan Gesture End
Pan gesture end event can be detected by checking its state with UIGestureRecognizerStateEnded
.
Check with the below code .
-(void) panAnim:(UIPanGestureRecognizer*) gestureRecognizer
{
if(gestureRecognizer.state == UIGestureRecognizerStateEnded)
{
//All fingers are lifted.
}
}
From Apple documentation
A panning gesture is continuous. It
begins (UIGestureRecognizerStateBegan)
when the minimum number of fingers
allowed (minimumNumberOfTouches) has
moved enough to be considered a pan.
It changes
(UIGestureRecognizerStateChanged) when
a finger moves while at least the
minimum number of fingers are pressed
down. It ends
(UIGestureRecognizerStateEnded) when
all fingers are lifted.
Read more about UIPanGestureRecognizer
Related Topics
Swift: How to Add a Class Method in 'string" Extension
iOS 12 Wkwebview Not Working with Redirects
Bridgetoobjectivec Not Available on Swift Beta 5
Swift - How to Deal with Uncaught Exception
Wkwebview Won't Load (Nsviewcontroller, Os X)
Get Png Representation of Nsimage in Swift
Decoding a Nested Array in Swift 4
Remove from Array of Anycancellable When Publisher Finishes
Variable with Getter/Setter Cannot Have Initial Value, on Overridden Stored Property
Combined Watch Os and iOS Framework
Swift: Parse, Query Date Field Based on Nsdate()
Perform Segue After UIalertcontroller Is Dismissed
Enum for Buttonstyle in Swiftui
Create a Generic Swift Function to Return an Array of Core Data Entities