Как распознать свайп во всех 4 направлениях

Мне нужно использовать смахивание, чтобы распознать жест смахивания вниз, а затем вправо. Но на быстром UISwipeGestureRecognizer есть предопределенное правильное направление .. И я не знаю, как сделать это для использования других направлений ..


person user3739367    schedule 13.06.2014    source источник


Ответы (17)


Вам необходимо иметь по одному UISwipeGestureRecognizer для каждого направления. Это немного странно, потому что свойство UISwipeGestureRecognizer.direction представляет собой битовую маску в стиле параметров, но каждый распознаватель может обрабатывать только одно направление. Вы можете отправить их все одному обработчику, если хотите, и отсортировать их там или отправить их разным обработчикам. Вот одна реализация:

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
        }
    }
}
person Nate Cook    schedule 14.06.2014
comment
каждый распознаватель может обрабатывать только одно направление - это неправда. См. stackoverflow.com/questions/16184539/ - person Sergey Skoblikov; 17.05.2015
comment
каждый распознаватель может обрабатывать только одно направление - это правда в Swift и ложь в Objective-C, чтобы быть конкретным. - person King-Wizard; 06.06.2015
comment
Вам не нужно добавлять UISwipeGestureRecognizerDirection перед .Down ect. Просто используйте swipeDown.direction = .Down, если достаточно. Просто подсказка =) - person Paul Peelen; 28.08.2015
comment
можем ли мы добавить один и тот же объект gestureRecogniser в несколько представлений? Я пробовал, но не работал. - person Max; 14.10.2015
comment
если вы выполните подход @Sergey Skoblikovs быстро (выполняя swipe.direction = [.Right,.Down,.Up,.Left]), распознаватель даже не будет вызван, возможно, это проблема Swift, но на данный момент не работает. - person Knight0fDragon; 18.11.2015
comment
Вместо того, чтобы создавать несколько организаторов жестов смахивания, которые все вызывают одну и ту же функцию swipeGesture.direction = UISwipeGestureRecognizerDirection.right self.view.addGestureRecognizer(swipeGesture) swipeGesture.direction = UISwipeGestureRecognizerDirection.left self.view.addGestureRecognizer(swipeGesture) - person Vrezh Gulyan; 19.11.2016
comment
я думаю, вам нужен @objc перед func respondToSwipeGesture, чтобы это работало в Swift 4 - person mway; 27.05.2019
comment
Вы правы, что вам нужен индивидуальный жест для каждого направления, но у вас может быть жест с более чем одним значением направления, например. swipe.direction = [.left, .right]. Смысл этого в том, что распознаватель жестов сработает, если произойдет одно из этих направлений, и не будет различать их. RawValue для перечисления UIGestureRecognizer.Direction: 1-вправо, 2-влево, 4-вверх, 8-вниз. Установка swipe.direction = [.left, .right] даст swipe.direction = 3, когда вы запросите жест в селекторе. - person leafcutter; 21.04.2020
comment
Для более позднего поисковика в Swift 5 перед методом func respondToSwipeGesture по-прежнему требуется @objc. - person zionpi; 03.11.2020

Мне просто захотелось внести свой вклад, в итоге выглядит более элегантно:

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)
}
person Alexandre Cassagne    schedule 03.12.2015
comment
self.addGestureRecognizer(gesture) вызвал у меня ошибку. Исправлено было self.view.addGestureRecognizer(gesture);. - person ahitt6345; 05.01.2016
comment
@ ahitt6345 Я использовал свой код в подклассе UIView, но вы абсолютно правы, если находитесь в UIViewController! - person Alexandre Cassagne; 05.02.2016
comment
Чистый, лучший ответ для меня. - person Christopher Smit; 20.10.2017

Из раскадровки:

  1. Добавьте в представление четыре распознавателя жестов смахивания.
  2. Задайте для каждого целевое направление из инспектора атрибутов. Вы можете выбрать вправо, влево, вверх или вниз
  3. Один за другим выберите распознаватель жестов смахивания, нажмите Ctrl + перетащите на контроллер просмотра. Вставьте имя (скажем, leftGesture, rightGesture, upGesture и downGesture), измените соединение на: Action и введите: UISwipeGestureRecognizer

Из вашего viewController:

@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")
}  
person user3099333    schedule 18.11.2015
comment
По этому ответу вам не нужно писать много кода, но вы используете раскадровку и связи между раскадровкой и вашим кодом. В случае, если разработчик предпочитает работать таким образом, этот ответ может быть проще, но если разработчик предпочитает больше работать над кодированием, определенно первый ответ будет лучшим. - person user3099333; 19.11.2015
comment
Я использовал 4 жеста смахивания вместо одного, и большая часть рабочей нагрузки приходится на раскадровку, а не на кодирование. - person user3099333; 20.11.2015

Похоже, что за последнее время все изменилось. В XCode 7.2 работает следующий подход:

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)
}

Проверено в симуляторе на iOS 8.4 и 9.2 и на реальном устройстве 9.2.

Или, используя удобное расширение mlcollard, здесь:

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

swipeGesture.direction = [.Down, .Up]
self.view.addGestureRecognizer(swipeGesture)
person Bogdan Farca    schedule 20.01.2016
comment
Селектор может быть вызван, но направление отправителя неверное. Другими словами, этот подход хорош, если вам не нужно знать направление смахивания, но не иначе. - person Robert Gummesson; 05.04.2016
comment
Больше не работает. В Swift 3 контекст должен быть предоставлен первому значению: [UISwipeGestureRecognizerDirection.right, .left, .up, .down] - person Brent Faust; 01.05.2017

Apple Swift версии 3.1 - Xcode версии 8.3 (8E162)

Удобный способ из подхода Александра Кассаньи

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")
    }
}
person John    schedule 30.03.2017
comment
В этой конкретной сборке вам нужно запустить defaults write com.apple.dt.xcode IDEPlaygroundDisableSimulatorAlternateFramebuffer -bool YES в Терминале, чтобы исправить ошибку на некотором оборудовании. Это должно быть исправлено в новой версии Xcode - person Allison; 30.03.2017

В Swift 4.2 и Xcode 9.4.1

Добавьте делегата анимации CAAnimationDelegate в свой класс

//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.
        })
}

Если вы хотите удалить жест из представления, используйте этот код

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)
                }
            }
        }
    }
}

Вызовите эту функцию как

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

Таким образом вы можете написать оставшиеся направления и, пожалуйста, будьте осторожны, есть ли у вас режим прокрутки или нет снизу вверх и наоборот

Если у вас есть режим прокрутки, вы получите конфликт для сверху вниз и обратный просмотр жестов.

person iOS    schedule 04.06.2018

UISwipeGestureRecognizer имеет свойство direction, которое имеет следующее определение:

var direction: UISwipeGestureRecognizerDirection

Допустимое направление смахивания для этого распознавателя жестов.


Проблема со Swift 3.0.1 (и ниже) в том, что даже если UISwipeGestureRecognizerDirection соответствует _5 _ следующий фрагмент будет скомпилирован, но не даст ожидаемого положительного результата:

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

В качестве обходного пути вам нужно будет создать UISwipeGestureRecognizer для каждого желаемого direction.


Следующий код игровой площадки показывает, как реализовать несколько UISwipeGestureRecognizer для одного и того же UIView и того же selector с помощью метода map массива:

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
person Imanou Petit    schedule 11.11.2016
comment
та же проблема все еще в xcode 8.3 - скомпилирована, но не работает - я получил только левую и правую эту спину UISwipeGestureRecognizerDirection(rawValue: 15) - person John; 30.03.2017

Жест смахивания в 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")
    }
}
person Lijith Vipin    schedule 26.07.2019

Проведите пальцем по экрану до нужного вам представления или полного представления viewcontroller в Swift 5 и XCode 11 на основе @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")
    }
}
person Egzon P.    schedule 03.11.2019

Сначала создайте baseViewController и добавьте viewDidLoad этот код "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
             }
         }
     }  
}

И используйте этот baseController класс:

class YourViewController: BaseViewController {
    // its done. Swipe successful
    //Now you can use all the Controller you have created without writing any code.    
}
person ikbal    schedule 06.09.2018

В Swift 5

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

Покопавшись немного:

Самый короткий способ добавления свайпов для всех 4 направлений:

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
}
person NeonGloss    schedule 15.09.2019

Просто более крутой быстрый синтаксис для ответа Нейта:

[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)
 })
person AmitP    schedule 07.09.2017

Легкий. Просто следуйте приведенному ниже коду и наслаждайтесь.

//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
        }
    }
}
person Super Developer    schedule 19.09.2017

Это можно сделать, просто объявив одну функцию, которая будет обрабатывать все ваши направления UISwipeGestureRecognizer. Вот мой код:

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)

Вот функция, которая будет обрабатывать функциональность смахивания:

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
        }
    }
}
person Shakti    schedule 28.07.2017

Вот так: (Swift 4.2.1)

UISwipeGestureRecognizer.Direction.init(
  rawValue: UISwipeGestureRecognizer.Direction.left.rawValue |
            UISwipeGestureRecognizer.Direction.right.rawValue |
            UISwipeGestureRecognizer.Direction.up.rawValue |
            UISwipeGestureRecognizer.Direction.down.rawValue
)
person jeudesprits    schedule 05.11.2018
comment
Добавьте описание к вашему коду, чтобы он стал лучше. - person Poul Bak; 05.11.2018

Для Swift 5 он обновлен

//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)

    }
person swiftBoy    schedule 10.08.2019
comment
Как это ответ на вопрос ОП? Проблема заключалась в том, чтобы найти элегантный способ добавить несколько направлений в распознаватель жестов смахивания. - person shashwat; 23.09.2019