Как добавить сенсорное событие в UIView? - PullRequest
264 голосов
/ 11 января 2011

Как добавить сенсорное событие в UIView?
Я стараюсь:

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)] autorelease];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];
// ERROR MESSAGE: UIView may not respond to '-addTarget:action:forControlEvents:'

Я не хочу создавать подкласс и перезаписывать

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

Ответы [ 13 ]

559 голосов
/ 12 января 2011

В iOS 3.2 и выше вы можете использовать распознаватели жестов. Например, вот как вы бы обработали событие касания:

//The setup code (in viewDidLoad in your view controller)
UITapGestureRecognizer *singleFingerTap = 
  [[UITapGestureRecognizer alloc] initWithTarget:self 
                                          action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleFingerTap];

//The event handling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
  CGPoint location = [recognizer locationInView:[recognizer.view superview]];

  //Do stuff here...
}

Существует также множество встроенных жестов. Посмотрите документы для обработки событий iOS и UIGestureRecognizer. У меня также есть несколько примеров кода на github , которые могут помочь.

114 голосов
/ 09 сентября 2015

Распознаватели жестов

Существует ряд часто используемых сенсорных событий (или жестов), о которых вы можете получать уведомления, когда добавляете к своему представлению Распознаватель жестов .Следующие типы жестов поддерживаются по умолчанию:

  • UITapGestureRecognizer Коснитесь (короткое касание экрана один или несколько раз)
  • UILongPressGestureRecognizer Длинное касание (длительное касание экрана)
  • UIPanGestureRecognizer Панорамирование (перемещение пальцем по экрану)
  • UISwipeGestureRecognizer Размах (быстрое движение пальца)
  • UIPinchGestureRecognizer Щепотка (движение двумя пальцами вместе или врозь - обычно для увеличения)
  • UIRotationGestureRecognizer Поворот (двигая двумя пальцами по кругу)

В дополнение к этому вы также можете сделать свой собственный распознаватель жестов.

Добавление жеста в Интерфейсном Разработчике

Перетащите распознаватель жестов из библиотеки объектов на ваше представление.

enter image description here

Управляйте перетаскиванием из жеста в структуре документа в представление.Код контроллера для создания розетки и действия.

enter image description here

Это должно быть установлено по умолчаниюа также убедитесь, что для User Action Enabled установлено значение true для вашего просмотра.

enter image description here

Добавление жеста программным способом

Чтобы добавить жест программно, вы (1) создаете распознаватель жестов, (2) добавляете его в представление и (3) создаете метод, который вызывается при распознавании жеста.

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var myView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1. create a gesture recognizer (tap gesture)
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))

        // 2. add the gesture recognizer to a view
        myView.addGestureRecognizer(tapGesture)
    }

    // 3. this method is called when a tap is recognized
    @objc func handleTap(sender: UITapGestureRecognizer) {
        print("tap")
    }
}

Примечания

  • Параметр sender является необязательным.Если вам не нужна ссылка на этот жест, вы можете не указывать его.Однако, если вы это сделаете, удалите (sender:) после имени метода действия.
  • Именование метода handleTap было произвольным.Назовите его как хотите, используя action: #selector(<strong>someMethodName</strong>(sender:)).

Дополнительные примеры

Вы можете изучить распознаватели жестов, которые я добавил в эти представления, чтобы увидеть, как они работают.

enter image description here

Вот код этого проекта:

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var tapView: UIView!
    @IBOutlet weak var doubleTapView: UIView!
    @IBOutlet weak var longPressView: UIView!
    @IBOutlet weak var panView: UIView!
    @IBOutlet weak var swipeView: UIView!
    @IBOutlet weak var pinchView: UIView!
    @IBOutlet weak var rotateView: UIView!
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Tap
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        tapView.addGestureRecognizer(tapGesture)

        // Double Tap
        let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
        doubleTapGesture.numberOfTapsRequired = 2
        doubleTapView.addGestureRecognizer(doubleTapGesture)

        // Long Press
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gesture:)))
        longPressView.addGestureRecognizer(longPressGesture)

        // Pan
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(gesture:)))
        panView.addGestureRecognizer(panGesture)

        // Swipe (right and left)
        let swipeRightGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
        let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
        swipeRightGesture.direction = UISwipeGestureRecognizerDirection.right
        swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.left
        swipeView.addGestureRecognizer(swipeRightGesture)
        swipeView.addGestureRecognizer(swipeLeftGesture)

        // Pinch
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(gesture:)))
        pinchView.addGestureRecognizer(pinchGesture)

        // Rotate
        let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotate(gesture:)))
        rotateView.addGestureRecognizer(rotateGesture)

    }

    // Tap action
    @objc func handleTap() {
        label.text = "Tap recognized"

        // example task: change background color
        if tapView.backgroundColor == UIColor.blue {
            tapView.backgroundColor = UIColor.red
        } else {
            tapView.backgroundColor = UIColor.blue
        }

    }

    // Double tap action
    @objc func handleDoubleTap() {
        label.text = "Double tap recognized"

        // example task: change background color
        if doubleTapView.backgroundColor == UIColor.yellow {
            doubleTapView.backgroundColor = UIColor.green
        } else {
            doubleTapView.backgroundColor = UIColor.yellow
        }
    }

    // Long press action
    @objc func handleLongPress(gesture: UILongPressGestureRecognizer) {
        label.text = "Long press recognized"

        // example task: show an alert
        if gesture.state == UIGestureRecognizerState.began {
            let alert = UIAlertController(title: "Long Press", message: "Can I help you?", preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }

    // Pan action
    @objc func handlePan(gesture: UIPanGestureRecognizer) {
        label.text = "Pan recognized"

        // example task: drag view
        let location = gesture.location(in: view) // root view
        panView.center = location
    }

    // Swipe action
    @objc func handleSwipe(gesture: UISwipeGestureRecognizer) {
        label.text = "Swipe recognized"

        // example task: animate view off screen
        let originalLocation = swipeView.center
        if gesture.direction == UISwipeGestureRecognizerDirection.right {
            UIView.animate(withDuration: 0.5, animations: {
                self.swipeView.center.x += self.view.bounds.width
            }, completion: { (value: Bool) in
                self.swipeView.center = originalLocation
            })
        } else if gesture.direction == UISwipeGestureRecognizerDirection.left {
            UIView.animate(withDuration: 0.5, animations: {
                self.swipeView.center.x -= self.view.bounds.width
            }, completion: { (value: Bool) in
                self.swipeView.center = originalLocation
            })
        }
    }

    // Pinch action
    @objc func handlePinch(gesture: UIPinchGestureRecognizer) {
        label.text = "Pinch recognized"

        if gesture.state == UIGestureRecognizerState.changed {
            let transform = CGAffineTransform(scaleX: gesture.scale, y: gesture.scale)
            pinchView.transform = transform
        }
    }

    // Rotate action
    @objc func handleRotate(gesture: UIRotationGestureRecognizer) {
        label.text = "Rotate recognized"

        if gesture.state == UIGestureRecognizerState.changed {
            let transform = CGAffineTransform(rotationAngle: gesture.rotation)
            rotateView.transform = transform
        }
    }
}

Примечания

  • ВыМожно добавить несколько распознавателей жестов для одного представления.Ради простоты, однако, я этого не делал (за исключением жеста смахивания).Если вам нужно для вашего проекта, вы должны прочитать документацию распознавателя жестов .Это довольно понятно и полезно.
  • Известные проблемы с моими примерами выше: (1) Панорамирование сбрасывает свой кадр при следующем событии жеста.(2) При первом пролистывании изображение смахивает с неправильного направления.(Эти ошибки в моих примерах не должны влиять на ваше понимание того, как работают распознаватели жестов.)
50 голосов
/ 05 декабря 2011

Я думаю, вы можете просто использовать

UIControl *headerView = ...
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];

Я имею в виду headerView расширяется от UIControl.

17 голосов
/ 06 октября 2016

Swift 3 & Swift 4

import UIKit

extension UIView {
  func addTapGesture(tapNumber: Int, target: Any, action: Selector) {
    let tap = UITapGestureRecognizer(target: target, action: action)
    tap.numberOfTapsRequired = tapNumber
    addGestureRecognizer(tap)
    isUserInteractionEnabled = true
  }
}

Использование

yourView.addTapGesture(tapNumber: 1, target: self, action: #selector(yourMethod))
17 голосов
/ 14 апреля 2013

На основании принятого ответа вы можете определить макрос:

#define handle_tap(view, delegate, selector) do {\
    view.userInteractionEnabled = YES;\
    [view addGestureRecognizer: [[UITapGestureRecognizer alloc] initWithTarget:delegate action:selector]];\
} while(0)

Этот макрос использует ARC, поэтому нет вызова release.

Использование макросапример:

handle_tap(userpic, self, @selector(onTapUserpic:));
9 голосов
/ 05 марта 2015

Этого можно добиться, добавив в свой код Gesture Recogniser.

Шаг 1: ViewController.m:

// Declare the Gesture.
UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] 
                                          initWithTarget:self 
                                          action:@selector(handleTap:)];
gesRecognizer.delegate = self;

// Add Gesture to your view.
[yourView addGestureRecognizer:gesRecognizer]; 

Шаг 2: ViewController.m:

// Declare the Gesture Recogniser handler method.
- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer{
   NSLog(@"Tapped");
}

ПРИМЕЧАНИЕ: здесь yourView в моем случае было @property (strong, nonatomic) IBOutlet UIView *localView;

РЕДАКТИРОВАТЬ: * localView - это белое поле в Main.storyboard снизу

enter image description here

enter image description here

5 голосов
/ 12 октября 2018

In Swift 4.2 и Xcode 10

Используйте UITapGestureRecognizer для добавления события касания

//Add tap gesture to your view
let tap = UITapGestureRecognizer(target: self, action: #selector(handleGesture))
yourView.addGestureRecognizer(tap)

// GestureRecognizer
@objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
//Write your code here
}

Если вы хотите использовать SharedClass

//This is my shared class
import UIKit

class SharedClass: NSObject {

    static let sharedInstance = SharedClass()

    //Tap gesture function
    func addTapGesture(view: UIView, target: Any, action: Selector) {
        let tap = UITapGestureRecognizer(target: target, action: action)
        view.addGestureRecognizer(tap)
    }
} 

У меня в ViewController 3 представления, которые называются view1, view2 и view3.

override func viewDidLoad() {
    super.viewDidLoad()
    //Add gestures to your views
    SharedClass.sharedInstance.addTapGesture(view: view1, target: self, action: #selector(handleGesture))
    SharedClass.sharedInstance.addTapGesture(view: view2, target: self, action: #selector(handleGesture))
    SharedClass.sharedInstance.addTapGesture(view: view3, target: self, action: #selector(handleGesture2))

}

// GestureRecognizer
@objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
    print("printed 1&2...")
}
// GestureRecognizer
@objc func handleGesture2(gesture: UITapGestureRecognizer) -> Void {
    print("printed3...")
}
5 голосов
/ 21 июня 2017

Свифт 3:

let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGestureRecognizer(_:)))
view.addGestureRecognizer(tapGestureRecognizer)

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}
5 голосов
/ 24 августа 2015

Вот версия Swift:

// MARK: Gesture Extensions
extension UIView {

    func addTapGesture(#tapNumber: Int, target: AnyObject, action: Selector) {
        let tap = UITapGestureRecognizer (target: target, action: action)
        tap.numberOfTapsRequired = tapNumber
        addGestureRecognizer(tap)
        userInteractionEnabled = true
    }

    func addTapGesture(#tapNumber: Int, action: ((UITapGestureRecognizer)->())?) {
        let tap = BlockTap (tapCount: tapNumber, fingerCount: 1, action: action)
        addGestureRecognizer(tap)
        userInteractionEnabled = true
    }
}
0 голосов
/ 15 января 2018

Почему бы вам, ребята, не попробовать SSEventListener ?

Вам не нужно создавать какой-либо распознаватель жестов и отделять свою логику от другого метода. SSEventListener поддерживает установку блоков прослушивателя в представлении для прослушивания жеста одним касанием, жеста двойного касания и жеста N касанием, если хотите, и жеста длинного нажатия. Установка прослушивателя с одним касанием становится следующим образом:

[view ss_addTapViewEventListener:^(UITapGestureRecognizer *recognizer) { ... } numberOfTapsRequired:1];

...