Wie füge ich einem UIView ein Touch-Ereignis hinzu?

280

Wie füge ich einem UIView ein Touch-Ereignis hinzu?
Ich versuche:

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

Ich möchte keine Unterklasse erstellen und überschreiben

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
Manni
quelle
Für schnelle können Sie es von hier bekommen: stackoverflow.com/questions/28675209/…
Mr.Javed Multani

Antworten:

578

In iOS 3.2 und höher können Sie Gestenerkenner verwenden. So würden Sie beispielsweise mit einem Tap-Ereignis umgehen:

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

Es gibt auch eine Reihe von eingebauten Gesten. Lesen Sie die Dokumente zur Behandlung von iOS-Ereignissen und UIGestureRecognizer. Ich habe auch eine Menge Beispielcode auf Github , der helfen könnte.

Nathan Eror
quelle
Aber das ist das Überschreiben der Touch-Defautlt-Aktion der Ansicht. ¿Ist es möglich, die Standardberührungsaktion der Ansicht aufzurufen? So etwas wie [super touchBegan]? ...
M Penades
2
Was macht die CGPoint-Linie?
Zakdances
2
@yourfriendzak the CGPointrepräsentiert die Position des Wasserhahns in der Übersicht der getippten Ansicht. Mit diesem Punkt können Sie die getippte Ansicht (oder eine Geschwisteransicht) an die getappte Position verschieben. Dies ist im Handler nützlicher, UIPanGestureRecognizerwenn Sie die Ansicht über den Bildschirm ziehen möchten.
Nathan Eror
5
tolle prägnante Antwort, danke. aber meine Güte, wäre es nicht schön, wenn das ein bisschen einfacher wäre?! :)
Natbro
Es ist nicht schlecht, aber ich wünschte, es gäbe eine blockbasierte API wie github.com/neror/ftutils/blob/master/Headers/FTUtils/… . Xcode 4 unterstützt auch das Hinzufügen / Konfigurieren von Gestenerkennern in Interface Builder.
Nathan Eror
126

Gestenerkenner

Es gibt eine Reihe häufig verwendeter Berührungsereignisse (oder Gesten), über die Sie benachrichtigt werden können, wenn Sie Ihrer Ansicht einen Gestenerkenner hinzufügen . Die folgenden Gestenarten werden standardmäßig unterstützt:

  • UITapGestureRecognizer Tippen Sie auf (kurz oder mehrmals kurz auf den Bildschirm tippen)
  • UILongPressGestureRecognizer Lange Berührung (langes Berühren des Bildschirms)
  • UIPanGestureRecognizer Schwenken (Bewegen Sie Ihren Finger über den Bildschirm)
  • UISwipeGestureRecognizer Streichen (Finger schnell bewegen)
  • UIPinchGestureRecognizer Prise (zwei Finger zusammen oder auseinander bewegen - normalerweise zum Zoomen)
  • UIRotationGestureRecognizer Drehen (zwei Finger in kreisförmiger Richtung bewegen)

Darüber hinaus können Sie Ihren eigenen Gestenerkenner erstellen.

Hinzufügen einer Geste im Interface Builder

Ziehen Sie einen Gestenerkenner aus der Objektbibliothek in Ihre Ansicht.

Geben Sie hier die Bildbeschreibung ein

Steuern Sie das Ziehen von der Geste in der Dokumentübersicht auf Ihren View Controller-Code, um ein Outlet und eine Aktion zu erstellen.

Geben Sie hier die Bildbeschreibung ein

Dies sollte standardmäßig festgelegt sein, aber stellen Sie auch sicher, dass User Action Enabled für Ihre Ansicht auf true festgelegt ist.

Geben Sie hier die Bildbeschreibung ein

Programmgesteuertes Hinzufügen einer Geste

Um eine Geste programmgesteuert hinzuzufügen, erstellen Sie (1) eine Gestenerkennung, (2) fügen Sie sie einer Ansicht hinzu und (3) erstellen Sie eine Methode, die aufgerufen wird, wenn die Geste erkannt wird.

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

Anmerkungen

  • Der senderParameter ist optional. Wenn Sie keinen Verweis auf die Geste benötigen, können Sie ihn weglassen. Wenn Sie dies jedoch tun, entfernen Sie den (sender:)Namen der Methode nach der Aktion.
  • Die Benennung der handleTapMethode war willkürlich. Nennen Sie es wie Sie wollen .action: #selector(someMethodName(sender:))

Mehr Beispiele

Sie können die Gestenerkenner untersuchen, die ich diesen Ansichten hinzugefügt habe, um zu sehen, wie sie funktionieren.

Geben Sie hier die Bildbeschreibung ein

Hier ist der Code für dieses Projekt:

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

Anmerkungen

  • Sie können einer einzelnen Ansicht mehrere Gestenerkenner hinzufügen. Der Einfachheit halber habe ich das jedoch nicht getan (mit Ausnahme der Wischgeste). Wenn Sie dies für Ihr Projekt benötigen, sollten Sie die Dokumentation zur Gestenerkennung lesen . Es ist ziemlich verständlich und hilfreich.
  • Bekannte Probleme mit meinen obigen Beispielen: (1) Die Schwenkansicht setzt ihren Rahmen beim nächsten Gestenereignis zurück. (2) Die Wischansicht kommt beim ersten Wischen aus der falschen Richtung. (Diese Fehler in meinen Beispielen sollten jedoch Ihr Verständnis der Funktionsweise von Gestenerkennern nicht beeinträchtigen.)
Suragch
quelle
2
Ihre Antwort ist sehr nett und hilfreich mit einer detaillierten Beschreibung. Und deshalb habe ich eine Stimme, die Sie auch beantworten. Aber Sie haben gerade eine Anweisung verpasst, die Sie meiner Meinung nach in Ihre Antwort aufnehmen müssen, da Sie sie ausführlich erklärt haben. In dieser Anweisung wird "<Ihre Ansicht> .EnableUserInteraction = TRUE" festgelegt. Ich hoffe du stimmst mir zu.
Ähm. Vihar
3
Um diese Arbeit an einem zu machen UIView, müssen Sie auch hinzufügen:self.isUserInteractionEnabled = true;
Neiker
52

Ich denke, Sie können einfach verwenden

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

Ich meine, HeaderView erstreckt sich von UIControl.

LiCheng
quelle
7
Dies ist die bessere Antwort. UITapGestureRecognizerist kein Ersatz für UIControlEventTouchDown. A besteht Tapnormalerweise aus UIControlEventTouchDownund UIControlEventTouchUpInside.
Ohho
62
A UIViewist kein a UIControlund hat daher keinen Zugriff auf addTarget:action:forControlEvents:.
Robert Joseph
9
Beachten Sie auch, dass ein UIControl von UIView erbt. Für meine Zwecke musste ich lediglich einen einfachen Wechsel vom Unterklassentyp durchführen.
Brezeln1337
1
Sie können die Klasse auf UIControl @RobertJoseph setzen. Wechseln Sie zur xib-Datei und setzen Sie die View Custom-Klasse auf UIControl. Jetzt können Sie Ereignis darin behandeln ..
Zar E Ahmer
2
Warum ist dies wieder eine bessere Lösung, da ich die Vererbung nur ändere, um mit Abgriffen umzugehen?
Anthony Glyadchenko
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
  }
}

Verwenden

yourView.addTapGesture(tapNumber: 1, target: self, action: #selector(yourMethod))
Indrajit Sinh Rayjada
quelle
Vielen Dank. Funktioniert super!
Mikrasya
1
Ich liebe das! Hinzufügen zu allen Projekten;)
Budidino
17

Basierend auf der akzeptierten Antwort können Sie ein Makro definieren:

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

Dieses Makro verwendet ARC, daher gibt es keinen releaseAufruf.

Beispiel für die Verwendung von Makros:

handle_tap(userpic, self, @selector(onTapUserpic:));
Rudyryk
quelle
4
Wenn Sie die Ansicht im Storyboard erstellen, vergessen Sie nicht, die Option "Benutzerinteraktion aktiviert" zu aktivieren.
David
wo wir Makros in .h oder .m definieren sollen und wie der Name der Parameter lauten soll. Ich meine, #define handle_tap (UIView-Ansicht, Delegierter Delegierter, SEL-Selektor) tun ..
Zar E Ahmer
8

Sie können dies erreichen, indem Sie Gestenerkenner in Ihren Code einfügen.

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

Schritt 2: ViewController.m:

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

HINWEIS: Hier war yourView in meinem Fall @property (strong, nonatomic) IBOutlet UIView *localView;

BEARBEITEN : * localView ist das weiße Feld in Main.storyboard von unten

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Annu
quelle
Ich habe mehrere Ansichten, also kann ich die Absender-ID?
Moin Shirazi
Sie müssen zur inneren Unteransicht gehen, dann können Sie den Absender paas .--------- für (UIView * -Ansicht in self.topicScrollView.subviews) {// In die Übersicht gehen if ([view isKindOfClass: [UIButton-Klasse]]) {// Gehe zu dieser bestimmten Ansicht // Hier hast du bis zu diesem Punkt erreicht. }}
Annu
8

In Swift 4.2 und Xcode 10

Verwenden Sie UITapGestureRecognizer zum Hinzufügen eines Berührungsereignisses

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

Wenn Sie SharedClass verwenden möchten

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

Ich habe 3 Ansichten in meinem ViewController mit den Namen view1, view2 und 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...")
}
iOS
quelle
6

Hier ist eine schnelle 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
    }
}
Esqarrouth
quelle
was ist BlockTap?
Er Yifei
1
Oh Mann, habe diesen Teil vergessen. Es ist eine benutzerdefinierte Funktion. Hier: github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/…
Esqarrouth
5

Swift 3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}
Giang
quelle
1

Scheint heutzutage ganz einfach. Dies ist die Swift-Version.

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

@objc func viewTapped(recognizer: UIGestureRecognizer)
{
    //Do what you need to do!
}
daj mi speakój
quelle
0

Hier ist ios tapgesture; Zuerst müssen Sie eine Aktion für GestureRecognizer erstellen, nachdem Sie den folgenden Code unter die Aktion geschrieben haben, wie unten gezeigt

- (IBAction)tapgesture:(id)sender

{


[_password resignFirstResponder];


[_username resignFirstResponder];

NSLog(@" TapGestureRecognizer  tapped");

}
sathish
quelle
0

Eine andere Möglichkeit ist das Hinzufügen einer transparenten Schaltfläche zur Ansicht

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

Und dann Handle Click:

- (void)buttonClicked:(id)sender
{}
thanhbinh84
quelle
0

Erstellen Sie einen Gestenerkenner (Unterklasse), der Berührungsereignisse wie z touchesBegan. Danach können Sie es der Ansicht hinzufügen.

Auf diese Weise verwenden Sie die Komposition anstelle der Unterklasse (was die Anforderung war).

Geri Borbás
quelle
0

Warum probiert ihr SSEventListener nicht aus ?

Sie müssen keine Gestenerkennung erstellen und Ihre Logik von einer anderen Methode trennen. SSEventListenerUnterstützt das Festlegen von Listener-Blöcken in einer Ansicht, um auf eine Geste mit einem Tippen, eine Geste mit zwei Tippen und eine Geste mit N-Tippen zu warten, wenn Sie möchten, sowie auf eine Geste mit langem Drücken. Das Einstellen eines einzelnen Tippgesten-Listeners wird folgendermaßen:

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

Shengsheng
quelle
0

Ziel c:

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

Schnell:

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

Die Frage lautet:

Wie füge ich einem UIView ein Touch- Ereignis hinzu?

Es wird nicht nach einem Tap- Ereignis gefragt .

Insbesondere möchte OP implementieren UIControlEventTouchDown

Umschalten der UIViewauf UIControldie richtige Antwort hier , weil Gesture Recognisersich weiß nichts über .touchDown, .touchUpInside, .touchUpOutsideusw.

Darüber hinaus erbt UIControl von UIView, sodass Sie keine Funktionalität verlieren.

Wenn Sie nur tippen möchten, können Sie den Gestenerkenner verwenden. Wenn Sie jedoch eine genauere Kontrolle wünschen, wie in dieser Frage gefordert, benötigen Sie UIControl.

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

janakmshah
quelle