Swift UIGestureRecognizer Touchdown - ios

Is it possible to capture touchdown and longpress with UIGestureRecognizer?
func gestureSetup() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapButton:")
tapTempoButton.addGestureRecognizer(tapGestureRecognizer)
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
longPressRecognizer.minimumPressDuration = 1.0
tapTempoButton.addGestureRecognizer(longPressRecognizer)
}
func tapButton(sender: UITapGestureRecognizer) {
// On touch down update UI and play sound
}

example: Gestures on UITextLabel
//Called on Label
let rotationGesture = UIRotationGestureRecognizer(target: self, action: "handleRotation:")
rotationGesture.delegate = self
let tapToDeleteTextGesture = UITapGestureRecognizer(target: self, action: "tapToDeleteText:")
tapToDeleteTextGesture.numberOfTapsRequired = 2
textLabel?.addGestureRecognizer(rotationGesture)
textLabel?.addGestureRecognizer(tapToDeleteTextGesture)
func handleRotation(recognizer: UIRotationGestureRecognizer){
let state = recognizer.state
if (state == UIGestureRecognizerState.Began || state == UIGestureRecognizerState.Changed){
if let view = recognizer.view {
view.transform = CGAffineTransformRotate(view.transform, recognizer.rotation)
recognizer.rotation = 0
}
}
}
func tapToDeleteText(recognizer: UITapGestureRecognizer){
if let view = recognizer.view {
view.removeFromSuperview()
}
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Add add the longPressGesture and you'll be set.

Related

Not able to add UITapGestureRecognizer and UILongPressGestureRecognizer to a UIButton

I am using the following code snippet to add the gesture recogniser :
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(attachImage))
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress))
tapGesture.numberOfTapsRequired = 1
cell.image.addGestureRecognizer(tapGesture)
cell.image.addGestureRecognizer(longGesture)
#objc func longPress(_ btn : UIButton) {
selectedImageIndex = btn.tag
}
#objc func attachImage(_ btn : UIButton) {
selectedImageIndex = btn.tag
}
I am getting the following error when I press the button
unrecognized selector sent to instance 0x2802ec000
Change the functions as follows
#objc func longPress(_ sender : UILongPressGestureRecognizer) {
if let btn = sender.view {
selectedImageIndex = btn.tag
}
}
#objc func attachImage(_ sender : UITapGestureRecognizer) {
if let btn = sender.view {
selectedImageIndex = btn.tag
}
}
And change gesture initialization as follows
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(attachImage(_:)))
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
If you add gesture on imageView then you have to enable isUserInteractionEnabled.
imageView.isUserInteractionEnabled = true
And If you add gesture on UIButton then
#IBOutlet weak var button: UIButton!
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, #selector (tapGestureActionHandler(_:))) //Tap function will call when user tap on button
let longGesture = UILongPressGestureRecognizer(target: self, #selector(longGestureActionHandler(_:))) //Long function will call when user long press on button.
tapGesture.numberOfTapsRequired = 1
button.addGestureRecognizer(tapGesture)
button.addGestureRecognizer(longGesture)
}
#objc func tapGestureActionHandler(_ gesture: UITapGestureRecognizer) {
print("Tap happend")
}
#objc func longGestureActionHandler(_ gesture: UILongPressGestureRecognizer) {
print("Long press")
}

How do I create a UISwipeGestureRecognizer programatically

private let swipeUp: UISwipeGestureRecognizer = {
let swiper = UISwipeGestureRecognizer(target: self, action: #selector(movedUp))
swiper.direction = .up
return swiper
}()
private let swipeDown: UISwipeGestureRecognizer = {
let swiper = UISwipeGestureRecognizer(target: self, action: #selector(movedDown))
swiper.direction = .down
return swiper
}()
creating my swipeUp and swipeDown gesture recognizers
func movedUp(sender: UISwipeGestureRecognizer){
print("UP")
}
func movedDown(sender: UISwipeGestureRecognizer){
print("DOWN")
}
my functions to be called when the swipe is recieved
override func viewDidLoad() {
self.view.addGestureRecognizer(swipeUp)
self.view.addGestureRecognizer(swipeDown)
}
adding my gesture recognizers in viewDidLoad
my program runs, but nothing happens when i swipe, what am i doing wrong?
Thankyou everyone
Try this:
private lazy var swipeUp: UISwipeGestureRecognizer = {
let swiper = UISwipeGestureRecognizer(target: self, action: #selector(movedUp))
swiper.direction = .up
return swiper
}()
private lazy var swipeDown: UISwipeGestureRecognizer = {
let swiper = UISwipeGestureRecognizer(target: self, action: #selector(movedDown))
swiper.direction = .down
return swiper
}()
override func viewDidLoad()
{
super.viewDidLoad()
self.view.addGestureRecognizer(swipeUp)
self.view.addGestureRecognizer(swipeDown)
}
func movedUp(sender: UISwipeGestureRecognizer)
{
print("UP")
}
func movedDown(sender: UISwipeGestureRecognizer)
{
print("DOWN")
}
Have you tried func movedUp(sender: UIGestureRecognizer)

iOS: recognize pinch gestures but not two finger pans?

The goal is to only let pinch gestures get recognized if a two-finger pan is not in process.
This code allows both pinchGesture and two-finger panGestures, but they occur at the same time. This was based off this answer to use the gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer) function.
// Handle two-finger pans
let twoFingerPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(sceneViewPannedTwoFingers))
twoFingerPanRecognizer.minimumNumberOfTouches = 2
twoFingerPanRecognizer.maximumNumberOfTouches = 2
twoFingerPanRecognizer.delegate = self
sceneView.addGestureRecognizer(twoFingerPanRecognizer)
// Handle pinches
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(sceneViewPinched))
pinchGesture.delegate = self
sceneView.addGestureRecognizer(pinchGesture)
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UIPinchGestureRecognizer {
return false
} else {
return true
}
}
This code allows two-finger pans, but pinches do not work at all.
// Handle two-finger pans
let twoFingerPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(sceneViewPannedTwoFingers))
twoFingerPanRecognizer.minimumNumberOfTouches = 2
twoFingerPanRecognizer.maximumNumberOfTouches = 2
twoFingerPanRecognizer.delegate = self
sceneView.addGestureRecognizer(twoFingerPanRecognizer)
// Handle taps
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(sceneViewTapped))
sceneView.addGestureRecognizer(tapRecognizer)
// Handle pinches
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(sceneViewPinched))
pinchGesture.delegate = self
pinchGesture.requireGestureRecognizerToFail(twoFingerPanRecognizer)
sceneView.addGestureRecognizer(pinchGesture)
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Have you try like this
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if ((gestureRecognizer is UIPinchGestureRecognizer || gestureRecognizer is UIPanGestureRecognizer)
&& (otherGestureRecognizer is UIPinchGestureRecognizer || otherGestureRecognizer is UIPanGestureRecognizer)) {
return false
}
return true
}

Fail all other gestures

In my container controller, sometimes I have to add a gesture recognizer to a view to handle things. Is it possible to fail all the other gestures on said view and only execute the added gesture?
Option 1:
Right now, all the individual gestures are set to fail when the new gesture has been detected, but it doesn't seem very efficient to do it this way.
Option 2:
Another way is get the array of gestures of said view and set enabled to false for all the gestures inside the array.
What I'd like to do is set the delegate of the new gesture to the container controller and use one of the delegate methods to fail all other gestures when the new gesture has been detected.
If you want to remove other gesture recogniser and want keep one gesture which user used then you can do by detecting the direction of that gesture and then you can remove all other gestures and you can keep used gesture.
Here is complete working code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let swipeRight = UISwipeGestureRecognizer(target: self, action: Selector("rightSwiped:"))
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: Selector("leftSwiped:"))
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
self.view.addGestureRecognizer(swipeLeft)
let swipeDown = UISwipeGestureRecognizer(target: self, action: Selector("downSwiped:"))
swipeDown.direction = UISwipeGestureRecognizerDirection.Down
self.view.addGestureRecognizer(swipeDown)
let swipeUp = UISwipeGestureRecognizer(target: self, action: Selector("upSwiped:"))
swipeUp.direction = UISwipeGestureRecognizerDirection.Up
self.view.addGestureRecognizer(swipeUp)
}
func rightSwiped(recognizer: UISwipeGestureRecognizer)
{
println("right swiped ")
manageGesture(recognizer)
}
func manageGesture(recognizer: UISwipeGestureRecognizer) {
//First detect which gesture is used
if recognizer.direction == UISwipeGestureRecognizerDirection.Right {
println("Right")
if let recognizers = view.gestureRecognizers {
for recognizer in recognizers {
if recognizer.direction == UISwipeGestureRecognizerDirection.Right {
println("Called")
}else {
view.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
}
}
}
}else if recognizer.direction == UISwipeGestureRecognizerDirection.Left {
println("Left")
if let recognizers = view.gestureRecognizers {
for recognizer in recognizers {
if recognizer.direction == UISwipeGestureRecognizerDirection.Left {
println("Called")
}else {
view.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
}
}
}
}else if recognizer.direction == UISwipeGestureRecognizerDirection.Up {
println("Up")
if let recognizers = view.gestureRecognizers {
for recognizer in recognizers {
if recognizer.direction == UISwipeGestureRecognizerDirection.Up {
println("Called")
}else {
view.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
}
}
}
}else if recognizer.direction == UISwipeGestureRecognizerDirection.Down {
println("Down")
if let recognizers = view.gestureRecognizers {
for recognizer in recognizers {
if recognizer.direction == UISwipeGestureRecognizerDirection.Down {
println("Called")
}else {
view.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
}
}
}
}
}
func leftSwiped(recognizer: UISwipeGestureRecognizer)
{
println("left swiped ")
manageGesture(recognizer)
}
func downSwiped(recognizer: UISwipeGestureRecognizer)
{
println("down swiped ")
manageGesture(recognizer)
}
func upSwiped(recognizer: UISwipeGestureRecognizer)
{
println("Up swiped ")
manageGesture(recognizer)
}
}
Hope this is what you need.

Swift: Long Press Gesture Recognizer - Detect taps and Long Press

I want to wire an action such that if the gesture is a tap, it does animates an object in a particular way but if the press duration was more than .5 secs it does something else.
Right now, I just have the animation hooked up. I don't know how I can differentiate between a long press and a tap?
How do I access the press duration to achieve the above?
#IBAction func tapOrHold(sender: AnyObject) {
UIView.animateKeyframesWithDuration(duration, delay: delay, options: options, animations: {
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
self.polyRotate.transform = CGAffineTransformMakeRotation(1/3 * CGFloat(M_PI * 2))
})
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
self.polyRotate.transform = CGAffineTransformMakeRotation(2/3 * CGFloat(M_PI * 2))
})
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
self.polyRotate.transform = CGAffineTransformMakeRotation(3/3 * CGFloat(M_PI * 2))
})
}, completion: { (Bool) in
let vc : AnyObject! = self.storyboard?.instantiateViewControllerWithIdentifier("NextView")
self.showViewController(vc as UIViewController, sender: vc)
})
Define two IBActions and set one Gesture Recognizer to each of them. This way you can perform two different actions for each gesture.
You can set each Gesture Recognizer to different IBActions in the interface builder.
#IBAction func tapped(sender: UITapGestureRecognizer)
{
println("tapped")
//Your animation code.
}
#IBAction func longPressed(sender: UILongPressGestureRecognizer)
{
println("longpressed")
//Different code
}
Through code without interface builder
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapped:")
self.view.addGestureRecognizer(tapGestureRecognizer)
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
self.view.addGestureRecognizer(longPressRecognizer)
func tapped(sender: UITapGestureRecognizer)
{
println("tapped")
}
func longPressed(sender: UILongPressGestureRecognizer)
{
println("longpressed")
}
Swift 5
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
self.view.addGestureRecognizer(tapGestureRecognizer)
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressed))
self.view.addGestureRecognizer(longPressRecognizer)
#objc func tapped(sender: UITapGestureRecognizer){
print("tapped")
}
#objc func longPressed(sender: UILongPressGestureRecognizer) {
print("longpressed")
}
For swift2
let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
lpgr.minimumPressDuration = 0.5
lpgr.delaysTouchesBegan = true
lpgr.delegate = self
self.featuredCouponColView.addGestureRecognizer(lpgr)
Action
//MARK: - UILongPressGestureRecognizer Action -
func handleLongPress(gestureReconizer: UILongPressGestureRecognizer) {
if gestureReconizer.state != UIGestureRecognizerState.Ended {
//When lognpress is start or running
}
else {
//When lognpress is finish
}
}
For Swift 4.2/ Swift 5
let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
lpgr.minimumPressDuration = 0.5
lpgr.delaysTouchesBegan = true
lpgr.delegate = self
self.colVw.addGestureRecognizer(lpgr)
//MARK: - UILongPressGestureRecognizer Action -
#objc func handleLongPress(gestureReconizer: UILongPressGestureRecognizer) {
if gestureReconizer.state != UIGestureRecognizer.State.ended {
//When lognpress is start or running
}
else {
//When lognpress is finish
}
}
Through code without interface builder
// Global variables declaration
var longPressed = false
var selectedRow = 0
override func viewDidLoad() {
super.viewDidLoad()
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(ContactListTableViewController.handleLongPress(_:)))
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.allowableMovement = 15 // 15 points
longPressGesture.delegate = self
self.tableView.addGestureRecognizer(longPressGesture)
}
// Long tap work goes here !!
if (longPressed == true) {
if(tableView.cellForRowAtIndexPath(indexPath)?.accessoryType == .Checkmark){
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None
self.selectedRow -= 1
if(self.selectedRow == 0){
self.longPressed = false
}
} else {
self.selectedRow += 1
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark
}
} else if(self.selectedRow == 0) {
// Single tape work goes here !!
}
But the only problem is the long press gesture runs two times. If you have found any solution do comment below !
Swift 5 using interface builder
for the normal tap you can simply create a touch up inside action from your button.
for the long press, create an outlet for your button, create the tap gesture recognizer and set it to the button then create the selector method to perform the long press tasks.
#IBOutlet var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(addToListButtonLongPress(_:)))
longPressRecognizer.numberOfTouchesRequired = 1
longPressRecognizer.allowableMovement = 10
longPressRecognizer.minimumPressDuration = 0.5
myButton.addGestureRecognizer(longPressRecognizer)
}
// Connected to myButton in interface builder.
#IBAction func myButtonTapped(_ sender: UIButton) {
print("button tapped")
}
#objc func myButtonLongPressed(_ sender: UILongPressGestureRecognizer) {
print("button long pressed")
}

Resources