Bir UIView'a bir dokunma etkinliği nasıl eklenir?


280

UIView'a nasıl bir dokunma etkinliği ekleyebilirim?
Denerim:

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

Bir alt sınıf oluşturmak ve üzerine yazmak istemiyorum

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

Hızlı için buradan alabilirsiniz: stackoverflow.com/questions/28675209/…
Mr.Javed Multani

Yanıtlar:


578

İOS 3.2 ve sonraki sürümlerde, hareket tanıyıcıları kullanabilirsiniz. Örneğin, bir dokunma etkinliğini şu şekilde işlersiniz:

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

Bir sürü yerleşik jest de var. İOS olay işleme ve için dokümanlara göz atın UIGestureRecognizer. Ayrıca yardımcı olabilecek github üzerinde örnek kod bir demet var .


Ancak bu, görünümün dokunma varsayılan eyleminin üzerine yazılmasıdır. The Görünümün varsayılan dokunma eylemini çağırmak mümkün mü? [Süper dokunuşlar] gibi bir şey mi? ...
M Penades

2
CGPoint hattı ne işe yarar?
zakdances

2
@yourfriendzak, CGPointdokunulan görünümün denetiminde musluğun konumunu temsil eder. Dokunulan görünümü (veya bir kardeş görünümü) dokunulan konuma taşımak için bu noktayı kullanabilirsiniz. Bu, UIPanGestureRecognizergörünümü ekranın etrafında sürüklemek için işleyicide daha kullanışlıdır .
Nathan Eror

5
büyük özlü cevap, teşekkürler. ama sheesh, bu biraz daha kolay olsaydı iyi olmaz mıydı ?! :)
natbro

Çok kötü değil, ama keşke github.com/neror/ftutils/blob/master/Headers/FTUtils/… gibi bir blok tabanlı API olsaydı . Xcode 4, Arayüz Oluşturucu'da hareket tanıyıcıları ekleme / yapılandırma desteği de sunmaktadır.
Nathan Eror

126

Hareket Tanıyıcılar

Görünümünüze bir Hareket Tanıyıcı eklediğinizde size bildirilebilecek bir dizi yaygın olarak kullanılan dokunma etkinliği (veya jest) vardır . Aşağıdaki hareket türlerini varsayılan olarak destekliyorlar:

  • UITapGestureRecognizer Simgesine dokunun (ekrana kısa bir veya birkaç kez dokunun )
  • UILongPressGestureRecognizer Uzun dokunma (ekrana uzun süre dokunma)
  • UIPanGestureRecognizer Kaydırma (parmağınızı ekran boyunca hareket ettirme)
  • UISwipeGestureRecognizer Kaydırma (parmağınızı hızla hareket ettirme)
  • UIPinchGestureRecognizer Sıkıştırma (iki parmağınızı birlikte veya birbirinden uzaklaştırma - genellikle yakınlaştırmak için)
  • UIRotationGestureRecognizer Döndürme (iki parmağınızı dairesel yönde hareket ettirme)

Bunlara ek olarak, kendi özel hareket tanımanızı da yapabilirsiniz.

Arayüz Oluşturucuya Hareket Ekleme

Bir hareket tanıyıcıyı nesne kitaplığından görünümünüze sürükleyin.

resim açıklamasını buraya girin

Çıkış ve İşlem yapmak için Belge Anahatındaki hareketten Görünüm Denetleyici kodunuza sürüklemeyi kontrol edin.

resim açıklamasını buraya girin

Bu varsayılan olarak ayarlanmalıdır, ancak görünümünüz için Kullanıcı İşlemi Etkin öğesinin true olarak ayarlandığından emin olun .

resim açıklamasını buraya girin

Programlı Bir Hareket Ekleme

Programlı bir hareket eklemek için, (1) bir hareket tanıyıcı oluşturursunuz, (2) bir görünüme eklersiniz ve (3) hareket tanınırken çağrılan bir yöntem yaparsınız.

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

notlar

  • senderParametre isteğe bağlıdır. Jest için bir referansa ihtiyacınız yoksa, dışarıda bırakabilirsiniz. Ancak bunu yaparsanız (sender:), işlem sonrası yöntem adını kaldırın .
  • handleTapYöntemin adlandırılması keyfiydi. Kullanmak istediğiniz her şeyi adlandırın .action: #selector(someMethodName(sender:))

Daha fazla örnek

Nasıl çalıştıklarını görmek için bu görünümlere eklediğim jest tanıyıcıları inceleyebilirsiniz.

resim açıklamasını buraya girin

İşte bu proje için kod:

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

notlar

  • Tek bir görünüme birden fazla hareket tanıyıcı ekleyebilirsiniz. Basitlik uğruna, bunu yapmadım (kaydırma hareketi hariç). Projeniz için gerekiyorsa, jest tanıyıcı belgelerini okumalısınız . Oldukça anlaşılabilir ve yararlı.
  • Yukarıdaki örneklerimle ilgili bilinen sorunlar: (1) Yatay kaydırma görünümü, sonraki hareket etkinliğinde çerçevesini sıfırlar. (2) Kaydırma görünümü, ilk kaydırmada yanlış yönden gelir. (Örneklerimdeki bu hatalar, Hareket Tanıyıcıların nasıl çalıştığına ilişkin anlayışınızı etkilememelidir.)

2
Cevabınız ayrıntılı açıklama ile gerçekten güzel ve yararlı. Ve bu yüzden oy verdim, sen de cevap ver. Ama tam olarak açıkladığınız gibi cevabınıza eklemeniz gerektiğini düşündüğüm bir talimatı kaçırdınız. Bu talimat "<görünümünüz> .EnableUserInteraction = DOĞRU" ayarı ile ilgilidir. Umarım bana katılıyorsun.
Er. Vihar

3
Bu işi yapmak UIViewiçin aşağıdakileri de eklemeniz gerekir:self.isUserInteractionEnabled = true;
neiker

52

Bence sadece

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

Yani headerView UIControl uzanır.


7
Bu daha iyi cevap. UITapGestureRecognizeryerine geçmez UIControlEventTouchDown. A Tapgenellikle UIControlEventTouchDownve öğelerinden oluşur UIControlEventTouchUpInside.
ohho

62
A UIViewbir değildir UIControlve bu nedenle erişimi yoktur addTarget:action:forControlEvents:.
RobertJoseph

9
Ayrıca bir UIControl'ün UIView'tan miras aldığını unutmayın. Benim amacım için tek yapmam gereken, alt sınıf tipinin basit bir geçişiydi.
pretzels1337

1
sınıfını UIControl @RobertJoseph olarak ayarlayabilirsiniz. xib dosyasına gidin ve View Custom sınıfını UIControl olarak ayarlayın. şimdi olayı işleyebilirsin ..
Zar E Ahmer

2
Öyleyse neden sadece muslukları işlemek için mirasımı değiştirdiğim için bu daha iyi bir çözüm?
Anthony Glyadchenko

21

Hızlı 3 ve Hızlı 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
  }
}

kullanım

yourView.addTapGesture(tapNumber: 1, target: self, action: #selector(yourMethod))

Teşekkürler. Harika çalışıyor!
Mikrasya

1
Bunu sev! Tüm projelere ekleme;)
budidino

17

Kabul edilen cevaba dayanarak bir makro tanımlayabilirsiniz:

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

Bu makro ARC kullanıyor, bu yüzden releaseçağrı yok .

Makro kullanım örneği:

handle_tap(userpic, self, @selector(onTapUserpic:));

4
Görünümü film şeridinde oluşturursanız, "kullanıcı etkileşimi etkin" seçeneğini etkinleştirmeyi unutmayın.
david

Burada makroları .h veya .m olarak tanımlamamız ve parametrelerin adı ne olmalıdır. #define handle_tap demek (UIView görünümü, Delege delegesi, SEL seçici) ..
Zar E Ahmer

8

Kodunuza Hareket Tanıyıcı ekleyerek bunu başarabilirsiniz.

Adım 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]; 

Adım 2: ViewController.m:

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

NOT: burada benim durumumda View oldu @property (strong, nonatomic) IBOutlet UIView *localView;

EDIT: * localView Main.storyboard aşağıdan beyaz kutu

resim açıklamasını buraya girin

resim açıklamasını buraya girin


i gönderen kimliği yapabilirsiniz böylece çoklu görünüm yaşıyorum?
Moin Shirazi

İç alt görünüme gitmelisiniz, sonra göndereni parolalayabilirsiniz .--------- için (self.topicScrollView.subviews UIView * görünümü) {// [UIButton class]]) {// Söz konusu görünüme gidin // Burada o ana kadar ulaştınız. }}
Annu

8

In Swift 4.2 ve Xcode 10

Dokunmatik etkinlik eklemek için UITapGestureRecognizer'ı kullanın

//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'ı kullanmak istiyorsanız

//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 içinde view1, view2 ve view3 adlı 3 görünüm var.

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

Heres Swift versiyonu:

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

nedir BlockTap?
He Yifei 何 一 非

1
Ah adamım, o kısmı unuttum. Bu özel bir işlev. Burada: github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/…
Esqarrouth

5

Hızlı 3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}

1

Bugünlerde oldukça basit görünüyor. Bu Swift versiyonudur.

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

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

0

İşte ios tapgesture; Öncelikle aşağıda gösterildiği gibi eylemin altına aşağıdaki kodu yazdıktan sonra GestureRecognizer için eylem oluşturmanız gerekir

- (IBAction)tapgesture:(id)sender

{


[_password resignFirstResponder];


[_username resignFirstResponder];

NSLog(@" TapGestureRecognizer  tapped");

}

0

Başka bir yol da görünüme şeffaf bir düğme eklemektir

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

Ardından, tıklamayı işleyin:

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

0

Dokunmatik etkinlikleri uygulayacak bir hareket tanıyıcı (alt sınıf) oluşturun. touchesBegan . Bundan sonra görünüme ekleyebilirsiniz.

Bu şekilde kompozisyonu alt sınıflandırma (istek) olarak kullanacaksınız.


0

Neden SSEventListener'ı denemiyorsunuz ?

Herhangi bir hareket tanıyıcı oluşturmanıza ve mantığınızı başka bir yönteme ayırmanıza gerek yoktur. SSEventListenertek dokunma hareketini, çift dokunma hareketini ve isterseniz N-dokunma hareketini ve uzun basma hareketini dinlemek için dinleyici bloklarını ayarlamayı destekler. Tek bir dokunma hareketi dinleyicisi ayarlamak şu şekilde olur:

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


0

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)

Soru soruyor:

UIView'a nasıl bir dokunma etkinliği ekleyebilirim ?

Bir hafifçe vurma etkinliği istemiyor .

Özellikle OP uygulamak istiyor UIControlEventTouchDown

Switching UIViewiçin UIControldoğru cevabı çünkü burada olduğunu Gesture Recognisershakkında hiçbir şey bilmiyorum .touchDown, .touchUpInside,.touchUpOutside vb

Ayrıca, UIControl UIView'den devralınır, böylece herhangi bir işlevsellik kaybetmezsiniz.

İstediğiniz tek şey bir dokunuşsa, Hareket Tanıyıcı'yı kullanabilirsiniz. Ancak, daha hassas kontrol istiyorsanız, bu sorunun istediği gibi, UIControl'e ihtiyacınız olacak.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.