Comment reconnaître le balayage dans les 4 directions

131

Je dois utiliser le balayage pour reconnaître le geste de balayage vers le bas, puis vers la droite. Mais sur UISwipeGestureRecognizer rapide a prédéterminé la bonne direction .. Et je ne sais pas comment faire cela pour utiliser d'autres directions.

user3739367
la source

Réponses:

324

Vous devez en avoir un UISwipeGestureRecognizerpour chaque direction. C'est un peu bizarre car la UISwipeGestureRecognizer.directionpropriété est un masque de bits de style options, mais chaque module de reconnaissance ne peut gérer qu'une seule direction. Vous pouvez les envoyer tous au même gestionnaire si vous le souhaitez, et les trier là-bas, ou les envoyer à différents gestionnaires. Voici une implémentation:

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
    swipeRight.direction = .right
    self.view.addGestureRecognizer(swipeRight)

    let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
    swipeDown.direction = .down
    self.view.addGestureRecognizer(swipeDown)
}

@objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {

    if let swipeGesture = gesture as? UISwipeGestureRecognizer {

        switch swipeGesture.direction {
        case .right:
            print("Swiped right")
        case .down:
            print("Swiped down")
        case .left:
            print("Swiped left")
        case .up:
            print("Swiped up")
        default:
            break
        }
    }
}

Swift 3:

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
    swipeRight.direction = UISwipeGestureRecognizerDirection.right
    self.view.addGestureRecognizer(swipeRight)

    let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
    swipeDown.direction = UISwipeGestureRecognizerDirection.down
    self.view.addGestureRecognizer(swipeDown)
}

func respondToSwipeGesture(gesture: UIGestureRecognizer) {
    if let swipeGesture = gesture as? UISwipeGestureRecognizer {
        switch swipeGesture.direction {
        case UISwipeGestureRecognizerDirection.right:
            print("Swiped right")
        case UISwipeGestureRecognizerDirection.down:
            print("Swiped down")
        case UISwipeGestureRecognizerDirection.left:
            print("Swiped left")
        case UISwipeGestureRecognizerDirection.up:
            print("Swiped up")
        default:
            break
        }
    }
}
Nate Cook
la source
"chaque outil de reconnaissance ne peut gérer qu'une seule direction" - ce n'est pas vrai. Voir stackoverflow.com/questions/16184539/…
Sergey Skoblikov
3
"chaque outil de reconnaissance ne peut gérer qu'une seule direction" - C'est vrai en Swift et faux en Objective-C pour être précis.
King-Wizard
13
Vous n'avez pas à ajouter UISwipeGestureRecognizerDirectiondevant .Downect. Juste utiliser swipeDown.direction = .Downsi cela est suffisant. Juste un conseil =)
Paul Peelen
pouvons-nous ajouter le même objet gestureRecogniser à plus d'une vue? J'ai essayé mais pas travaillé.
Max
3
si vous appliquez l'approche de @Sergey Skoblikovs rapidement, (en faisant swipe.direction = [.Right,.Down,.Up,.Left]), le module de reconnaissance ne sera même pas appelé, c'est peut-être un problème avec swift, mais pour le moment, cela ne fonctionne pas.
Knight0fDragon
55

J'avais juste envie de contribuer, ça a l'air plus élégant à la fin:

func addSwipe() {
    let directions: [UISwipeGestureRecognizerDirection] = [.Right, .Left, .Up, .Down]
    for direction in directions {
        let gesture = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipe:"))
        gesture.direction = direction
        self.addGestureRecognizer(gesture)
    }
}

func handleSwipe(sender: UISwipeGestureRecognizer) {
    print(sender.direction)
}
Alexandre Cassagne
la source
10
self.addGestureRecognizer(gesture)a causé une erreur pour moi. Ce qui a corrigé c'était self.view.addGestureRecognizer(gesture);.
ahitt6345
1
@ ahitt6345 J'utilisais mon code dans une UIViewsous - classe, mais vous avez absolument raison si vous êtes dans un UIViewController!
Alexandre Cassagne
1
Propre, meilleure réponse pour moi.
Christopher Smit
22

À partir du storyboard:

  1. Ajoutez quatre outils de reconnaissance de gestes à votre vue.
  2. Définissez chacun d'eux avec la direction cible de l'inspecteur d'attributs. Vous pouvez sélectionner droite, gauche, haut ou bas
  3. Un par un, sélectionnez le module de reconnaissance de geste de balayage, contrôlez + faites glisser vers votre contrôleur de vue. Insérez le nom (disons leftGesture, rightGesture, upGesture et downGesture), changez la connexion en: Action et tapez en: UISwipeGestureRecognizer

De votre vueContrôleur:

@IBAction func rightGesture(sender: UISwipeGestureRecognizer) {
    print("Right")
}
@IBAction func leftGesture(sender: UISwipeGestureRecognizer) {
    print("Left")
}
@IBAction func upGesture(sender: UISwipeGestureRecognizer) {
    print("Up")
}

@IBAction func downGesture(sender: UISwipeGestureRecognizer) {
    print("Down")
}  
user3099333
la source
5
Par cette réponse, vous n'avez pas besoin d'écrire beaucoup de codes mais vous utilisez le storyboard et les connexions entre le storyboard et votre code. Dans le cas où le développeur préfère travailler de cette manière, cette réponse peut être plus simple, mais si le développeur préfère travailler davantage dans le codage, la première réponse est certainement la meilleure.
user3099333
J'ai utilisé 4 gestes de balayage au lieu d'un et une grande partie de la charge de travail se trouve dans le storyboard au lieu du codage.
user3099333
9

On dirait que les choses ont changé ces derniers temps. Dans XCode 7.2, l'approche suivante fonctionne:

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeGesture = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
    swipeGesture.direction = [.Down, .Up]
    self.view.addGestureRecognizer(swipeGesture)
}

func handleSwipe(sender: UISwipeGestureRecognizer) {
    print(sender.direction)
}

Testé dans Simulator sur iOS 8.4 et 9.2 et sur un appareil réel sur 9.2.

Ou, en utilisant l' extension pratique de mlcollard ici :

let swipeGesture = UISwipeGestureRecognizer() {
    print("Gesture recognized !")
}

swipeGesture.direction = [.Down, .Up]
self.view.addGestureRecognizer(swipeGesture)
Bogdan Farca
la source
5
Le sélecteur peut être appelé mais la direction de l'expéditeur est incorrecte. En d'autres termes, cette approche convient si vous n'avez pas besoin de connaître la direction du balayage, mais pas autrement.
Robert Gummesson
Ne fonctionne plus. Dans Swift 3, le contexte doit être fourni à la première valeur:[UISwipeGestureRecognizerDirection.right, .left, .up, .down]
Brent Faust
7

Apple Swift version 3.1 - Xcode version 8.3 (8E162)

Le moyen pratique de l'approche d' Alexandre Cassagne

let directions: [UISwipeGestureRecognizerDirection] = [.up, .down, .right, .left]
for direction in directions {
    let gesture = UISwipeGestureRecognizer(target: self, action: #selector(YourClassName.handleSwipe(gesture:)))
    gesture.direction = direction
    self.view?.addGestureRecognizer(gesture)   
}

func handleSwipe(gesture: UISwipeGestureRecognizer) {
    print(gesture.direction)
    switch gesture.direction {
    case UISwipeGestureRecognizerDirection.down:
        print("down swipe")
    case UISwipeGestureRecognizerDirection.up:
        print("up swipe")
    case UISwipeGestureRecognizerDirection.left:
        print("left swipe")
    case UISwipeGestureRecognizerDirection.right:
        print("right swipe")
    default:
        print("other swipe")
    }
}
John
la source
1
Avec cette version spécifique, vous devez exécuter defaults write com.apple.dt.xcode IDEPlaygroundDisableSimulatorAlternateFramebuffer -bool YESdans Terminal pour corriger un bogue sur certains matériels. Cela devrait être corrigé dans une nouvelle version de Xcode
Sirens
6

Dans Swift 4.2 et Xcode 9.4.1

Ajouter un délégué d'animation, CAAnimationDelegate à votre classe

//Swipe gesture for left and right
let swipeFromRight = UISwipeGestureRecognizer(target: self, action: #selector(didSwipeLeft))
swipeFromRight.direction = UISwipeGestureRecognizerDirection.left
menuTransparentView.addGestureRecognizer(swipeFromRight)

let swipeFromLeft = UISwipeGestureRecognizer(target: self, action: #selector(didSwipeRight))
swipeFromLeft.direction = UISwipeGestureRecognizerDirection.right
menuTransparentView.addGestureRecognizer(swipeFromLeft)

//Swipe gesture selector function
@objc func didSwipeLeft(gesture: UIGestureRecognizer) {
    //We can add some animation also
    DispatchQueue.main.async(execute: {
            let animation = CATransition()
            animation.type = kCATransitionReveal
            animation.subtype = kCATransitionFromRight
            animation.duration = 0.5
            animation.delegate = self
            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            //Add this animation to your view
            self.transparentView.layer.add(animation, forKey: nil)
            self.transparentView.removeFromSuperview()//Remove or hide your view if requirement.
        })
}

//Swipe gesture selector function
@objc func didSwipeRight(gesture: UIGestureRecognizer) {
        // Add animation here
        DispatchQueue.main.async(execute: {
            let animation = CATransition()
            animation.type = kCATransitionReveal
            animation.subtype = kCATransitionFromLeft
            animation.duration = 0.5
            animation.delegate = self
            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            //Add this animation to your view
            self.transparentView.layer.add(animation, forKey: nil)
            self.transparentView.removeFromSuperview()//Remove or hide yourview if requirement.
        })
}

Si vous souhaitez supprimer le geste de la vue, utilisez ce code

self.transparentView.removeGestureRecognizer(gesture)

Ex:

func willMoveFromView(view: UIView) {
    if view.gestureRecognizers != nil {
        for gesture in view.gestureRecognizers! {
            //view.removeGestureRecognizer(gesture)//This will remove all gestures including tap etc...
            if let recognizer = gesture as? UISwipeGestureRecognizer {
                //view.removeGestureRecognizer(recognizer)//This will remove all swipe gestures
                if recognizer.direction == .left {//Especially for left swipe
                    view.removeGestureRecognizer(recognizer)
                }
            }
        }
    }
}

Appelez cette fonction comme

//Remove swipe gesture
self.willMoveFromView(view: self.transparentView)

Comme ça, vous pouvez écrire les directions restantes et faites attention si vous avez une vue de défilement ou non de bas en haut et vice versa

Si vous avez une vue par défilement, vous obtiendrez un conflit de haut en bas et afficherez les gestes versa.

iOS
la source
4

UISwipeGestureRecognizera une directionpropriété qui a la définition suivante:

var direction: UISwipeGestureRecognizerDirection

La direction autorisée du balayage pour ce module de reconnaissance de gestes.


Le problème avec Swift 3.0.1 (et inférieur) est que même s'il UISwipeGestureRecognizerDirectionest conforme à OptionSet, l'extrait de code suivant sera compilé mais ne produira aucun résultat attendu positif:

// This compiles but does not work
let gesture = UISwipeGestureRecognizer(target: self, action: #selector(gestureHandler))
gesture.direction = [.right, .left, .up, .down]
self.addGestureRecognizer(gesture)

Pour contourner ce problème, vous devrez créer un UISwipeGestureRecognizerpour chaque fichier souhaité direction.


Le code Playground suivant montre comment implémenter plusieurs UISwipeGestureRecognizerpour le même UIViewet le même en selectorutilisant la mapméthode de Array :

import UIKit
import PlaygroundSupport

class SwipeableView: UIView {
    convenience init() {
        self.init(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
        backgroundColor = .red

        [UISwipeGestureRecognizerDirection.right, .left, .up, .down].map({
            let gesture = UISwipeGestureRecognizer(target: self, action: #selector(gestureHandler))
            gesture.direction = $0
            self.addGestureRecognizer(gesture)
        })
    }

    func gestureHandler(sender: UISwipeGestureRecognizer) {
        switch sender.direction {
        case [.left]:   frame.origin.x -= 10
        case [.right]:  frame.origin.x += 10
        case [.up]:     frame.origin.y -= 10
        case [.down]:   frame.origin.y += 10
        default:        break
        }
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        view.addSubview(SwipeableView())
    }
}

let controller = ViewController()
PlaygroundPage.current.liveView = controller
Imanou Petit
la source
le même problème toujours dans xcode 8.3 - compilé mais ne fonctionne pas - j'ai juste pour gauche et droite ce dosUISwipeGestureRecognizerDirection(rawValue: 15)
John
4

Faites glisser le geste vers la vue souhaitée ou la vue entière du contrôleur de vue dans Swift 5 et XCode 11 basé sur @Alexandre Cassagne

override func viewDidLoad() {
    super.viewDidLoad()

    addSwipe()
}

func addSwipe() {
    let directions: [UISwipeGestureRecognizer.Direction] = [.right, .left, .up, .down]
    for direction in directions {
        let gesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe))
        gesture.direction = direction
        self.myView.addGestureRecognizer(gesture)// self.view
    }
}

@objc func handleSwipe(sender: UISwipeGestureRecognizer) {
    let direction = sender.direction
    switch direction {
        case .right:
            print("Gesture direction: Right")
        case .left:
            print("Gesture direction: Left")
        case .up:
            print("Gesture direction: Up")
        case .down:
            print("Gesture direction: Down")
        default:
            print("Unrecognized Gesture Direction")
    }
}
Doci
la source
3

Geste de balayage dans Swift 5

  override func viewDidLoad() {
    super.viewDidLoad()
    let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
    swipeLeft.direction = .left
    self.view!.addGestureRecognizer(swipeLeft)

    let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
    swipeRight.direction = .right
    self.view!.addGestureRecognizer(swipeRight)

    let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
    swipeUp.direction = .up
    self.view!.addGestureRecognizer(swipeUp)

    let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
    swipeDown.direction = .down
    self.view!.addGestureRecognizer(swipeDown)
}

@objc func handleGesture(gesture: UISwipeGestureRecognizer) -> Void {
    if gesture.direction == UISwipeGestureRecognizer.Direction.right {
        print("Swipe Right")
    }
    else if gesture.direction == UISwipeGestureRecognizer.Direction.left {
        print("Swipe Left")
    }
    else if gesture.direction == UISwipeGestureRecognizer.Direction.up {
        print("Swipe Up")
    }
    else if gesture.direction == UISwipeGestureRecognizer.Direction.down {
        print("Swipe Down")
    }
}
Lijith Vipin
la source
2

Commencez par créer un baseViewControlleret ajoutez viewDidLoadce code "swift4":

class BaseViewController: UIViewController {             

     override func viewDidLoad() {
         super.viewDidLoad()
         let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiped))
         swipeRight.direction = UISwipeGestureRecognizerDirection.right
         self.view.addGestureRecognizer(swipeRight)
         let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swiped))
         swipeLeft.direction = UISwipeGestureRecognizerDirection.left
         self.view.addGestureRecognizer(swipeLeft)
     }

     // Example Tabbar 5 pages
     @objc func swiped(_ gesture: UISwipeGestureRecognizer) {
         if gesture.direction == .left {
            if (self.tabBarController?.selectedIndex)! < 5 {
                self.tabBarController?.selectedIndex += 1
            }
         } else if gesture.direction == .right {
             if (self.tabBarController?.selectedIndex)! > 0 {
                 self.tabBarController?.selectedIndex -= 1
             }
         }
     }  
}

Et utilisez cette baseControllerclasse:

class YourViewController: BaseViewController {
    // its done. Swipe successful
    //Now you can use all the Controller you have created without writing any code.    
}
Ikbal
la source
2

Dans Swift 5,

let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe))
swipeGesture.direction = [.left, .right, .up, .down]
view.addGestureRecognizer(swipeGesture)
nitin.agam
la source
1

Juste une syntaxe plus rapide et plus cool pour la réponse de Nate:

[UISwipeGestureRecognizerDirection.right,
 UISwipeGestureRecognizerDirection.left,
 UISwipeGestureRecognizerDirection.up,
 UISwipeGestureRecognizerDirection.down].forEach({ direction in
    let swipe = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
    swipe.direction = direction
    self.view.addGestureRecognizer(swipe)
 })
AmitP
la source
1

Facile. Suivez simplement le code ci-dessous et profitez-en.

//SwipeGestureMethodUsing
func SwipeGestureMethodUsing ()
{
    //AddSwipeGesture
    [UISwipeGestureRecognizerDirection.right,
     UISwipeGestureRecognizerDirection.left,
     UISwipeGestureRecognizerDirection.up,
     UISwipeGestureRecognizerDirection.down].forEach({ direction in
        let swipe = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
        swipe.direction = direction
        window?.addGestureRecognizer(swipe)
     })
}

//respondToSwipeGesture
func respondToSwipeGesture(gesture: UIGestureRecognizer) {

    if let swipeGesture = gesture as? UISwipeGestureRecognizer
    {
        switch swipeGesture.direction
        {
        case UISwipeGestureRecognizerDirection.right:
            print("Swiped right")
        case UISwipeGestureRecognizerDirection.down:
            print("Swiped down")
        case UISwipeGestureRecognizerDirection.left:
            print("Swiped left")
        case UISwipeGestureRecognizerDirection.up:
            print("Swiped up")
        default:
            break
        }
    }
}
Priyank Jotangiya
la source
1

Après avoir fouillé pendant un moment:

Le moyen le plus court d' ajouter des balayages pour les 4 directions est:

override func viewDidLoad() {
    super.viewDidLoad()    
    for direction in [UISwipeGestureRecognizer.Direction.down, .up, .left, .right]{
        let swipeGest = UISwipeGestureRecognizer(target: self, action: #selector(swipeAction(_:)))
        swipeGest.direction = direction
        self.view.addGestureRecognizer(swipeGest)
    }
} 

@objc func swipeAction(_ gesture: UISwipeGestureRecognizer){
    switch gesture.direction {
    case UISwipeGestureRecognizer.Direction.right:
        print("Swiped right")
    case UISwipeGestureRecognizer.Direction.down:
        print("Swiped down")
    case UISwipeGestureRecognizer.Direction.left:
        print("Swiped left")
    case UISwipeGestureRecognizer.Direction.up:
        print("Swiped up")
    default: break
}
NeonGloss
la source
0

Cela peut être fait en déclarant simplement une fonction qui gérera toutes vos directions de balayage UISwipeGestureRecognizer. Voici mon code:

let swipeGestureRight = UISwipeGestureRecognizer(target: self, action:#selector(ViewController.respondToSwipeGesture(_:)) )
swipeGestureRight.direction = UISwipeGestureRecognizerDirection.right
self.view .addGestureRecognizer(swipeGestureRight)

let swipeGestureLeft = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
swipeGestureLeft.direction = UISwipeGestureRecognizerDirection.left
self.view.addGestureRecognizer(swipeGestureLeft)

let swipeGestureUp = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
swipeGestureUp.direction = UISwipeGestureRecognizerDirection.up
self.view.addGestureRecognizer(swipeGestureUp)

let swipeGestureDown = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
swipeGestureDown.direction = UISwipeGestureRecognizerDirection.down
self.view.addGestureRecognizer(swipeGestureDown)

Voici la fonction qui gérera la fonctionnalité de swipedirection:

func respondToSwipeGesture(_ sender: UIGestureRecognizer) {
    if let swipeGesture = sender as? UISwipeGestureRecognizer {
        switch swipeGesture.direction {
            case UISwipeGestureRecognizerDirection.right:
                print("right swipe")
            case UISwipeGestureRecognizerDirection.left:
                print("leftSwipe")
            case UISwipeGestureRecognizerDirection.up:
                print("upSwipe")
            case UISwipeGestureRecognizerDirection.down:
                print("downSwipe")
            default:
                break
        }
    }
}
Shakti
la source
0

Juste comme ça: ( Swift 4.2.1 )

UISwipeGestureRecognizer.Direction.init(
  rawValue: UISwipeGestureRecognizer.Direction.left.rawValue |
            UISwipeGestureRecognizer.Direction.right.rawValue |
            UISwipeGestureRecognizer.Direction.up.rawValue |
            UISwipeGestureRecognizer.Direction.down.rawValue
)
jeudesprits
la source
2
Ajoutez une description à votre code, s'il vous plaît, cela le rendra meilleur.
Poul Bak
0

Pour Swift 5, il est mis à jour

//Add in ViewDidLoad
let gesture = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.handleSwipe))
        gesture.direction = .right
        self.view.addGestureRecognizer(gesture)

//Add New Method
@objc func handleSwipe(sender: UISwipeGestureRecognizer) {
        print("swipe direction is",sender.direction)

    }
swiftBoy
la source
En quoi est-ce une réponse à la question du PO? Le problème était de trouver un moyen élégant d'ajouter plusieurs directions à la reconnaissance de geste de balayage.
shashwat