Saya perlu mengimplementasikan fitur yang akan memanggil beberapa kode ketika saya mengetuk dua kali pada self.view (view of UIViewCotroller
). Tetapi masalah bahwa saya memiliki objek UI lain pada tampilan ini dan saya tidak ingin melampirkan objek pengenal apa pun ke semuanya. Saya menemukan metode ini di bawah cara memberi isyarat pada pandangan saya dan saya tahu cara kerjanya. Saat ini saya berada di depan handicap, cara mana yang harus dipilih untuk membuat pengenal ini mengabaikan subview. Ada ide? Terima kasih.
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.view addGestureRecognizer:doubleTap];
ios
uitapgesturerecognizer
Matrosov Alexander
sumber
sumber
Jawaban:
Anda harus mengadopsi
UIGestureRecognizerDelegate
protokol di dalamself
objek dan memanggil metode di bawah ini untuk memeriksa tampilan. Di dalam metode ini, periksa tampilan Andatouch.view
dan kembalikan bool yang sesuai (Ya / Tidak). Sesuatu seperti ini:- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([touch.view isDescendantOfView:yourSubView]) { return NO; } return YES; }
Edit: Tolong, periksa juga jawaban @ Ian!
Cepat 5
// MARK: UIGestureRecognizerDelegate methods, You need to set the delegate of the recognizer func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if touch.view?.isDescendant(of: tableView) == true { return false } return true }
sumber
-[UIGestureRecognizer requireGestureRecognizerToFail:]
dokumennya tetapi mungkin berfungsi tanpa mengubahnyaif
pengujian Anda gagal, implementasi Anda gagal mengembalikan BOOL; untuk gaya yang benar, kembalikan YA setelah blok if (menggunakan{ }
) atau dielse
cabang. Terima kasih, meskipun, menghemat sedikit bacaan saya.Pendekatan lain adalah dengan membandingkan jika tampilan sentuhan adalah tampilan isyarat, karena keturunan tidak akan melewati kondisi tersebut. Satu baris yang bagus dan sederhana:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return touch.view == gestureRecognizer.view }
sumber
Dan untuk varian Swift:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if touch.view.isDescendantOfView(yourSubView){ return false } return true }
Perlu diketahui,
isDescendantOfView
mengembalikanBoolean
nilai yang menunjukkan apakah penerima adalah subview dari tampilan tertentu atau identik dengan tampilan tersebut.sumber
Dengan Swift 5 dan iOS 12,
UIGestureRecognizerDelegate
ada metode yang disebutgestureRecognizer(_:shouldReceive:)
.gestureRecognizer(_:shouldReceive:)
memiliki deklarasi berikut:optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
Kode lengkap di bawah ini menunjukkan kemungkinan implementasi untuk
gestureRecognizer(_:shouldReceive:)
. Dengan kode ini, ketukan pada subviewViewController
tampilan (termasukimageView
) tidak akan memicuprintHello(_:)
metode.import UIKit class ViewController: UIViewController, UIGestureRecognizerDelegate { override func viewDidLoad() { super.viewDidLoad() let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(printHello)) tapGestureRecognizer.delegate = self view.addGestureRecognizer(tapGestureRecognizer) let imageView = UIImageView(image: UIImage(named: "icon")!) imageView.frame = CGRect(x: 50, y: 50, width: 100, height: 100) view.addSubview(imageView) // ⚠️ Enable user interaction for imageView so that it can participate to touch events. // Otherwise, taps on imageView will be forwarded to its superview and managed by it. imageView.isUserInteractionEnabled = true } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { // Prevent subviews of a specific view to send touch events to the view's gesture recognizers. if let touchedView = touch.view, let gestureView = gestureRecognizer.view, touchedView.isDescendant(of: gestureView), touchedView !== gestureView { return false } return true } @objc func printHello(_ sender: UITapGestureRecognizer) { print("Hello") } }
Implementasi alternatif
gestureRecognizer(_:shouldReceive:)
dapat berupa:func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return gestureRecognizer.view === touch.view }
Namun perlu diperhatikan bahwa kode alternatif ini tidak memeriksa apakah
touch.view
merupakan subview darigestureRecognizer.view
.sumber
Solusi cepat lengkap (delegasi harus diimplementasikan DAN ditetapkan untuk pengenal):
class MyViewController: UIViewController UIGestureRecognizerDelegate { override func viewDidLoad() { let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(onBaseTapOnly)) doubleTapRecognizer.numberOfTapsRequired = 2 doubleTapRecognizer.delegate = self self.view.addGestureRecognizer(doubleTapRecognizer) } func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if touch.view.isDescendantOfView(self.view){ return false } return true } func onBaseTapOnly(sender: UITapGestureRecognizer) { if sender.state == .Ended { //react to tap } } }
sumber
Varian menggunakan CGPoint yang Anda sentuh (SWIFT 4.0)
class MyViewController: UIViewController, UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { // Get the location in CGPoint let location = touch.location(in: nil) // Check if location is inside the view to avoid if viewToAvoid.frame.contains(location) { return false } return true } }
sumber
Hapus cara Swift
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return touch.view == self.view }
sumber
Perhatikan bahwa GestureRecognizer API telah berubah menjadi:
gestureRecognizer (_: shouldReceive :)
Perhatikan secara khusus indikator garis bawah (lewati) untuk label eksternal parameter pertama.
Menggunakan banyak contoh yang diberikan di atas, saya tidak menerima acara tersebut. Di bawah ini adalah contoh yang berfungsi untuk versi Swift (3+) saat ini.
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { var shouldReceive = false if let clickedView = touch.view { if clickedView == self.view { shouldReceive = true; } } return shouldReceive }
sumber
Ditambah solusi di atas, jangan lupa untuk memeriksa
User Interaction Enabled
sub-tampilan Anda.sumber
Saya harus mencegah gerakan pada pandangan anak. Satu-satunya hal yang berhasil adalah mengizinkan dan mempertahankan tampilan pertama dan mencegah isyarat di semua tampilan berikutnya:
var gestureView: UIView? = nil func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if (gestureView == nil || gestureView == touch.view){ gestureView = touch.view return true } return false }
sumber
Cepat 4:
touch.view
sekarang opsional, jadi berdasarkan jawaban @ Antoine:func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if let touchedView = touch.view, touchedView.isDescendant(of: deductibleBackgroundView) { return false } return true }
sumber
Jika Anda tidak ingin 'double-tap recogniser' Anda bertentangan dengan tombol dan / atau kontrol lain, Anda dapat mengatur
self
sebagaiUIGestureRecognizerDelegate
dan menerapkan:func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return !(touch.view is UIControl) }
sumber