Як додати сенсорну подію до UIView?


280

Як додати сенсорну подію до 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

Для стрижа ви можете отримати його тут: stackoverflow.com/questions/28675209 / ...
Mr.Javed Мултані

Відповіді:


578

У 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, який може допомогти.


Але це є перезаписом дефолтної дефолтної дії погляду. ¿Чи можна викликати дію в режимі торкання за замовчуванням? Щось на кшталт [супер дотикиБеган]? ...
M Penades

2
Що робить лінія CGPoint?
zakdances

2
@yourfriendzak CGPointявляє собою розташування крана в огляді представленого виду. Ви можете скористатися цією точкою для переміщення представленого виду (або подання побратимів) до місця, де викладено. Це корисніше в обробці UIPanGestureRecognizerдля перетягування вигляду по екрану.
Натан Ерор

5
чудова лаконічна відповідь, дякую. але sheesh, чи не було б добре, якби це було трохи легше ?! :)
natbro

Це не так вже й погано, але я б хотів, щоб існував API на основі блоків, наприклад github.com/neror/ftutils/blob/master/Headers/FTUtils/… . Xcode 4 також підтримує додавання / налаштування розпізнавачів жестів в Interface Builder.
Натан Ерор

126

Розпізнавачі жестів

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

  • UITapGestureRecognizer Торкніться (короткий дотик до екрана один чи кілька разів)
  • UILongPressGestureRecognizer Довгий дотик ( тривалий дотик до екрана)
  • UIPanGestureRecognizer Панорама (переміщення пальця по екрану)
  • UISwipeGestureRecognizer Проведіть пальцем (швидко рухається пальцем)
  • UIPinchGestureRecognizer Щип (переміщення двома пальцями разом або один від одного - зазвичай для збільшення)
  • UIRotationGestureRecognizer Поворот (переміщення двома пальцями в круговому напрямку)

На додаток до них, ви також можете зробити власний розпізнавальний жест.

Додавання жесту в програмі інтерфейсу

Перетягніть розпізнавальник жестів із бібліотеки об'єктів на ваш погляд.

введіть тут опис зображення

Контролюйте перетягування від жесту в контуру документа до коду контролера перегляду, щоб зробити розетку та дію.

введіть тут опис зображення

Це потрібно встановити за замовчуванням, але також переконайтеся, що для дії користувача включено значення True для вашого перегляду.

введіть тут опис зображення

Додавання жесту програмно

Щоб додати жест програмно, ви (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(someMethodName(sender:))

Більше прикладів

Ви можете вивчити розпізнавачі жестів, які я додав до цих поглядів, щоб побачити, як вони працюють.

введіть тут опис зображення

Ось код цього проекту:

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) Перегляд пальцем пальця відбувається з неправильного напрямку на першому пальці. (Ці помилки в моїх прикладах не повинні впливати на ваше розуміння того, як працюють засоби розпізнавання жестів.)

2
Ваша відповідь дуже приємна і корисна з детальним описом. І саме тому я маю на увазі і ви відповідаєте. Але ви просто пропустили одну інструкцію, яку, на мою думку, ви повинні включити у свою відповідь, так як ви її повністю пояснили. Ця інструкція стосується налаштування "<yourView> .EnableUserInteraction = TRUE". Я сподіваюся, ви погоджуєтесь зі мною.
Ер. Віхар

3
Для того, щоб зробити цю роботу над a, UIViewвам потрібно також додати:self.isUserInteractionEnabled = true;
neiker

52

Я думаю, ви можете просто використовувати

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

я маю на увазі headerView поширюється на UIControl.


7
Це краща відповідь. UITapGestureRecognizerне є заміною UIControlEventTouchDown. А Tapзазвичай складається з UIControlEventTouchDownі UIControlEventTouchUpInside.
ой

62
А UIViewне є UIControlі тому не має доступу до нього addTarget:action:forControlEvents:.
RobertJoseph

9
Також зауважте, що UIControl успадковує від UIView. Для моїх цілей я мав лише простий перемикач типу підкласу.
pretzels1337

1
ви можете встановити його клас на UIControl @RobertJoseph .. Перейдіть до файлу xib і встановіть для класу Перегляд користувачем UIControl. тепер ви можете впоратись із подією в ній ..
Zar E Ahmer

2
То чому це знову краще рішення, оскільки я змінюю спадщину просто для обробки кранів?
Антоній Глядченко

21

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

Дякую. Чудово працює!
Мікрася

1
Люблю це! Додавання до всіх проектів;)
budidino

17

На основі прийнятої відповіді можна визначити макрос:

#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:));

4
Якщо ви створюєте подання на дошці розкадрувань, не забудьте ввімкнути опцію "Включена взаємодія з користувачем".
Девід

де нам слід визначити макроси в .h або .m і якою має бути назва параметрів. я маю на увазі #define handle_tap (перегляд UIView, делегат-делегат, селектор SEL) роблять ..
Зар Е Ахмер

8

Цього можна досягти, додавши у свій код Recogniser 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");
}

ПРИМІТКА: тут у моєму випадку був вашView @property (strong, nonatomic) IBOutlet UIView *localView;

EDIT: * localView - це біле поле в Main.storyboard знизу

введіть тут опис зображення

введіть тут опис зображення


У мене є кілька переглядів, то чи можу я відправник
Мойн Ширазі

Вам потрібно перейти до внутрішнього підрозділу, тоді ви можете відмовити відправника. [Клас UIButton]]) {// Перейдіть до цього конкретного виду // Тут ви дійшли до цієї точки. }}
Ану

8

У 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...")
}

6

Ось версія 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
    }
}

що таке BlockTap?
He Yifei 何 一 非

1
О людино, забув цю частину. Це спеціальна функція. Тут: github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/…
Esqarrouth

5

Швидкий 3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}

1

Ці дні здаються досить простими. Це версія Swift.

let tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
    view.addGestureRecognizer(tap)

@objc func viewTapped(recognizer: UIGestureRecognizer)
{
    //Do what you need to do!
}

0

Ось ios tapgesture; Спочатку потрібно створити дію для GestureRecognizer після того, як записати код нижче під дією, як показано нижче

- (IBAction)tapgesture:(id)sender

{


[_password resignFirstResponder];


[_username resignFirstResponder];

NSLog(@" TapGestureRecognizer  tapped");

}

0

Ще один спосіб - додавання прозорої кнопки до перегляду

UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
b.frame = CGRectMake(0, 0, headerView.width, headerView.height);
[headerView addSubview:b];
[b addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];

А потім обробіть клацання:

- (void)buttonClicked:(id)sender
{}

0

Створіть розпізнавальник жестів (підклас), який буде реалізовувати сенсорні події, наприклад touchesBegan . Ви можете додати його до перегляду після цього.

Таким чином ви будете використовувати композицію замість підкласи (що було запитом).


0

Чому б вам не спробувати SSEventListener ?

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

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


0

Завдання-C:

UIControl *headerView = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];

Швидкий:

let headerView = UIControl(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: nextY))
headerView.addTarget(self, action: #selector(myEvent(_:)), for: .touchDown)

Питання задає:

Як додати сенсорну подію до UIView?

Чи не просити водопровідне подія.

Зокрема, ОП хоче впровадити UIControlEventTouchDown

Перемикання UIViewна UIControlправильну відповідь тут , тому що Gesture Recognisersнічого не знає про .touchDown, .touchUpInside, і .touchUpOutsideт.д.

Крім того, UIControl успадковує від UIView, так що ви не втрачаєте жодної функціональності.

Якщо все, що вам потрібно, - це крана, тоді ви можете скористатися інструментом розпізнавання жестів. Але якщо ви хочете більш точного контролю, як це запитує, вам знадобиться UIControl.

https://developer.apple.com/documentation/uikit/uicontrol?language=objc https://developer.apple.com/documentation/uikit/uigesturerecognizer?language=objc

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.