Jak dodać zdarzenie touch do interfejsu UIView?

Jak dodać zdarzenie dotykowe do interfejsu UIView?
Staram się:

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:'

Nie chcę tworzyć podklasy i nadpisywać

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
Author: Suragch, 2011-01-11

15 answers

W systemie iOS 3.2 i nowszych można używać rozpoznawania gestów. Na przykład w ten sposób można obsłużyć Zdarzenie tap:

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

Istnieje również kilka wbudowanych gestów. Sprawdź dokumenty do obsługi zdarzeń iOS i UIGestureRecognizer. Mam też kilka przykładowych kodów na github , które mogą pomóc.

 585
Author: Nathan Eror,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-01 04:16:41

Rozpoznawanie Gestów

Istnieje wiele powszechnie używanych zdarzeń dotykowych (lub gestów), o których możesz być powiadamiany po dodaniu do widoku narzędzia rozpoznawania gestów . Domyślnie obsługiwane są następujące typy gestów:

  • UITapGestureRecognizer dotknij (dotknij na krótko ekranu jeden lub więcej razy)
  • UILongPressGestureRecognizer długi dotyk (dotykanie ekranu przez długi czas)
  • UIPanGestureRecognizer Pan (poruszając palcem po screen)
  • UISwipeGestureRecognizer przesuń palcem (ruch palcem szybko)
  • UIPinchGestureRecognizer uszczypnij (przesuwając dwa palce razem lub osobno-zwykle w celu powiększenia)
  • UIRotationGestureRecognizer Obróć (poruszając dwoma palcami w kierunku kolistym)

Oprócz tych, można również zrobić własny rozpoznawania gestów niestandardowych.

Dodawanie gestu w Kreatorze interfejsów

Przeciągnij rozpoznawanie gestów z biblioteki obiektów na swój widok.

Tutaj wpisz opis obrazka

Sterowanie przeciąganiem z gestu w obrysie dokumentu do kodu kontrolera widoku, aby wykonać wyjście I Akcję.

Tutaj wpisz opis obrazka

Powinna być ustawiona domyślnie, ale także upewnij się, że User Action Enabled jest ustawiona na true dla Twojego widoku.

Tutaj wpisz opis obrazka

Dodawanie gestu programowo

Aby programowo dodać gest, należy (1) utworzyć rozpoznawanie gestów, (2) dodaj go do widoku i (3) Utwórz metodę, która zostanie wywołana, gdy gest zostanie rozpoznany.

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

Uwagi

  • parametr sender jest opcjonalny. Jeśli nie potrzebujesz odniesienia do gestu, możesz go pominąć. Jeśli to zrobisz, Usuń (sender:) po nazwie metody akcji.
  • Nazwa metody handleTap była Dowolna. Nazwij go jak chcesz używając action: #selector(someMethodName(sender:)).

Więcej Przykładów

Możesz studiować rozpoznawanie gestów że dodałem do tych poglądów, aby zobaczyć, jak działają.

Tutaj wpisz opis obrazka

Oto kod do tego projektu:

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

Uwagi

  • do jednego widoku można dodać wiele funkcji rozpoznawania gestów. Ze względu na prostotę, nie zrobiłem tego(z wyjątkiem gestu machnięcia). Jeśli potrzebujesz do swojego projektu, powinieneś przeczytać dokumentacja rozpoznawania gestów . Jest to dość zrozumiałe i pomocne.
  • Znane problemy z moje przykłady powyżej: (1) widok panoramiczny resetuje swoją klatkę przy następnym zdarzeniu gest. (2) widok Przesuń pochodzi z niewłaściwym kierunku przy pierwszym przesunięciu. (Te błędy w moich przykładach nie powinny mieć wpływu na zrozumienie, jak działają Rozpoznawacze gestów.)
 135
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Myślę, że możesz po prostu użyć

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

Chodzi mi o to, że headerView rozszerza się z UIControl.

 52
Author: LiCheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 01:37:53

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

Użyj

yourView.addTapGesture(tapNumber: 1, target: self, action: #selector(yourMethod))
 23
Author: Indrajit Sinh Rayjada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-28 07:13:07

Na podstawie zaakceptowanej odpowiedzi można zdefiniować makro:

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

To makro używa ARC, więc nie ma release wywołania.

Przykład użycia makra:

handle_tap(userpic, self, @selector(onTapUserpic:));
 17
Author: rudyryk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:07

W Swift 4.2 i Xcode 10

Użyj UITapGestureRecognizer aby dodać zdarzenie dotykowe

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

Jeśli chcesz użyć 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)
    }
} 

Mam 3 widoki w moim kontrolerze ViewController o nazwie view1, view2 i 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...")
}
 9
Author: iOS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-12 08:50:34

Możesz to osiągnąć, dodając rozpoznawanie gestów w kodzie.

Krok 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]; 

Krok 2: ViewController.m:

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

Uwaga: tutaj twój widok w moim przypadku był @property (strong, nonatomic) IBOutlet UIView *localView;

EDIT: *localView jest białym polem W Main.storyboard from below

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

 8
Author: Annu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-19 11:19:07

Heres a Swift version:

// 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
    }
}
 6
Author: Esqarrouth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-24 12:54:06

Swift 3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}
 5
Author: Giang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-21 06:19:49

W dzisiejszych czasach wydaje się to dość proste. To jest wersja Swift.

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

@objc func viewTapped(recognizer: UIGestureRecognizer)
{
    //Do what you need to do!
}
 1
Author: daj mi spokój,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-16 06:38:56

Objective-C:

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

Swift:

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

Pytanie zadaje:

Jak dodać zdarzenie touch do UIView?

To nie jest prośba o Zdarzenietap .

Konkretnie OP chce zaimplementować UIControlEventTouchDown

Zamiana UIView na UIControl jest tutaj właściwą odpowiedzią, ponieważ Gesture Recognisers Nie wiem nic o .touchDown, .touchUpInside, .touchUpOutside itd.

Dodatkowo, UIControl dziedziczy z UIView, więc nie tracisz żadnych funkcjonalność.

Jeśli chcesz tylko stuknąć, możesz użyć rozpoznawania gestów. Ale jeśli chcesz mieć lepszą kontrolę, o co prosi to pytanie, będziesz potrzebował UIControl.

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

 1
Author: janakmshah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-14 14:05:10

Oto iOS tapgesture; Najpierw musisz utworzyć akcję dla GestureRecognizer po wpisaniu poniższego kodu pod akcją, jak pokazano poniżej

- (IBAction)tapgesture:(id)sender

{


[_password resignFirstResponder];


[_username resignFirstResponder];

NSLog(@" TapGestureRecognizer  tapped");

}
 0
Author: sathish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 05:48:58

Innym sposobem jest dodanie przezroczystego przycisku do widoku

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];

A następnie uchwyć kliknięcie:

- (void)buttonClicked:(id)sender
{}
 0
Author: thanhbinh84,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-17 10:32:34

Utwórz podklasę rozpoznawania gestów, która zaimplementuje zdarzenia dotykowe, takie jak touchesBegan. Możesz dodać go do widoku po tym.

W ten sposób użyjesz kompozycji zamiast podklasowania(co było żądaniem).

 0
Author: Geri Borbás,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-13 17:11:13

Może spróbujecie SSEventListener ?

Nie musisz tworzyć żadnego rozpoznawania gestów i oddzielać logiki od innej metody. SSEventListener obsługuje ustawianie bloków słuchacza w widoku, aby słuchać gestu pojedynczego dotknięcia, gestu podwójnego dotknięcia i gestu N-dotknięcia, jeśli chcesz, i długie naciśnięcie gestu. Ustawienie gestu pojedynczego dotknięcia odbywa się w ten sposób:

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

 0
Author: Shengsheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-15 06:53:55