UITapGestureRecognizer स्वयं पर टैप करें। लेकिन साक्षात्कार को अनदेखा करें


93

मुझे एक ऐसी सुविधा लागू करने की आवश्यकता है जो आत्म कोड (डबल-व्यू UIViewCotroller) पर डबल टैप करने पर कुछ कोड को लागू करेगी । लेकिन समस्या यह है कि मेरे पास इस दृश्य पर अन्य UI ऑब्जेक्ट है और मैं उन सभी के लिए किसी भी पहचानकर्ता ऑब्जेक्ट को संलग्न नहीं करना चाहता हूं। मुझे यह तरीका नीचे दिया गया है कि कैसे मैं अपने दृष्टिकोण पर इशारा कर सकता हूं और मुझे पता है कि यह कैसे काम करता है। अभी मैं विकलांगों के सामने हूं कि इस पहचानकर्ता को चुनने के लिए कौन सा रास्ता चुनना है जो उप-भाग की अनदेखी कर रहा है। कोई विचार? धन्यवाद।

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.view addGestureRecognizer:doubleTap];

1
मुझे यकीन नहीं है, लेकिन क्या आपने पहचानकर्ता पर cancelsTouchesInView NO करने की कोशिश की है? इसलिए [doubleTap setCancelsTouchesInView: NO];
JDx

जवाबों:


142

आपको ऑब्जेक्ट के UIGestureRecognizerDelegateअंदर प्रोटोकॉल को अपनाना चाहिए selfऔर दृश्य की जांच के लिए नीचे दी गई विधि को कॉल करना चाहिए । इस पद्धति के अंदर, अपने विचार की जाँच करें touch.viewऔर उचित बूल (हाँ / नहीं) वापस करें। कुछ इस तरह:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if ([touch.view isDescendantOfView:yourSubView]) {
        return NO;
    }
    return YES;
}

संपादित करें: कृपया, @ इयान का उत्तर भी जांचें!

स्विफ्ट 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
}

एक और सवाल मेरे पास मेरे विचार पर कुछ बटन हैं जिन्हें काम करना है। मैं उनके लिए कुछ प्राथमिकता कैसे निर्धारित कर सकता हूं?
मटरू अलेक्जेंडर

यदि आपके बटन के अपने स्वयं के हावभाव पहचानकर्ता (संभावना) हैं, तो उनके इंटर्नल में खुदाई करें और उन्हें पकड़ें, और डॉक्स को पढ़ें, -[UIGestureRecognizer requireGestureRecognizerToFail:]लेकिन यह उन्हें मॉडिफाई किए बिना काम कर सकता है
bshirley

घंटे के लिए यह देख रहा था! धन्यवाद! ;)
मास्टरराज

यदि आपका ifपरीक्षण विफल हो जाता है, तो आपका कार्यान्वयन BOOL वापस करने में विफल रहता है; अगर एक ब्लॉक (उपयोग { }) या एक elseशाखा में उचित शैली वापसी के लिए हाँ । धन्यवाद, हालांकि, मुझे पढ़ने में थोड़ी बचत हुई।
RobP

2
एक दृश्य स्वयं का वंशज है इसलिए यह काम नहीं करता है ... (हालांकि समग्र दृष्टिकोण ठीक है, अन्य उत्तर देखें)
Ixx

107

एक अन्य दृष्टिकोण सिर्फ तुलना करना है अगर स्पर्श का दृष्टिकोण इशारों का दृश्य है, क्योंकि वंशज शर्त को पारित नहीं करेंगे। एक अच्छा, सरल वन-लाइनर:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return touch.view == gestureRecognizer.view
}

2
स्वीकृत उत्तर की तुलना में यह मेरे लिए बेहतर काम कर रहा है। बहुत अधिक संक्षिप्त।
सुमन रॉय

1
@ दृश्य पर टैप करने पर इस विधि को लागू नहीं किया जाता है।
Praburaj

1
शानदार संक्षिप्त जवाब!
scurioni

स्वीकृत जवाब से भी काम नहीं चला, लेकिन यह मेरे लिए त्रुटिपूर्ण था।
शालीन शाह

@Prabu पूरी तरह से क्योंकि इशारा पहचानकर्ता के प्रतिनिधि को इससे पहले निर्धारित किया जाना चाहिए
Kubba

23

और स्विफ्ट संस्करण के लिए:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if touch.view.isDescendantOfView(yourSubView){
        return false
    }
    return true
}

यह जानना अच्छा है, isDescendantOfViewएक रिटर्न Booleanका संकेत रिसीवर दिए गए दृश्य या उस दृश्य के समान की एक subview है कि क्या मूल्य।


1
अपनी कक्षा में UIGestureRecognizerDelegate सेट करना न भूलें!
फॉक्स5150

4
ऐसा करने के बजाए यदि वह कथन है, तो क्या आप इसे वापस नहीं कर सकते? वापसी! touch.view.isDescenders (of :ureureRecognizer.view) इसके अलावा, स्विफ्ट 3 में नया सिंटैक्स ^ ^
एडवर्डशेन्ज

12

स्विफ्ट 5 और आईओएस 12 के साथ, UIGestureRecognizerDelegateएक विधि कहा जाता है gestureRecognizer(_:shouldReceive:)gestureRecognizer(_:shouldReceive:)निम्नलिखित घोषणा है:

प्रतिनिधि से पूछें कि क्या एक इशारा पहचानकर्ता को एक स्पर्श का प्रतिनिधित्व करने वाली वस्तु प्राप्त होनी चाहिए।

optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool

नीचे दिए गए पूर्ण कोड के लिए एक संभावित कार्यान्वयन दिखाया गया है gestureRecognizer(_:shouldReceive:)। इस कोड के साथ, एक ViewControllerदृश्य के उप-भाग पर एक टैप (सहित imageView) printHello(_:)विधि को ट्रिगर नहीं करेगा ।

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

}

का एक वैकल्पिक कार्यान्वयन gestureRecognizer(_:shouldReceive:)हो सकता है:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return gestureRecognizer.view === touch.view
}

ध्यान दें कि यदि touch.viewयह सबव्यू है तो यह वैकल्पिक कोड चेक नहीं करता है gestureRecognizer.view


10

पूर्ण स्विफ्ट समाधान (प्रतिनिधि को लागू किया जाना चाहिए और पहचानकर्ता के लिए निर्धारित किया जाना चाहिए):

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

6

आपके द्वारा स्पर्श किए जाने वाले CGPoint का उपयोग कर भिन्न (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
  }
}

4

साफ स्विफ्ट रास्ता

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return touch.view == self.view
}

कभी भी iOS 13 में नहीं बुलाया जाता है, कम से कम swipeGestureRecognizer के साथ।
Chewie The Chorkie

यह इयान के जवाब के लिए कैसे अलग है?
स्वीटफा

3

ध्यान दें कि जेस्चर रिकॉग्निशन API बदल गया है:

gestureRecognizer (_: shouldReceive :)

पहले पैरामीटर के बाहरी लेबल के लिए अंडरस्कोर (स्किप) संकेतक का विशेष ध्यान रखें।

ऊपर दिए गए कई उदाहरणों का उपयोग करते हुए, मैं इस घटना को प्राप्त नहीं कर रहा था। नीचे एक उदाहरण है जो स्विफ्ट (3+) के वर्तमान संस्करणों के लिए काम करता है।

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
}

2

इसके अलावा उपरोक्त समाधान, User Interaction Enabledअपने उप-दृश्य की जांच करना न भूलें ।

यहां छवि विवरण दर्ज करें


2

मुझे बच्चे को देखने के इशारे को रोकना था। केवल एक चीज जो काम करती है वह है कि पहले दृश्य को अनुमति दें और अगले सभी विचारों में हावभाव को रोकें:

   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
     }

1

स्विफ्ट 4:

touch.view अब एक वैकल्पिक है, इसलिए @ एंटोनी के उत्तर पर आधारित है:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    if let touchedView = touch.view, touchedView.isDescendant(of: deductibleBackgroundView) {
        return false
    }
    return true
}

0

आप अपने 'दो बार स्पर्श करें recogniser' अपने बटन और / या अन्य नियंत्रण के साथ संघर्ष नहीं करना चाहते हैं, तो आप सेट कर सकते हैं selfके रूप में UIGestureRecognizerDelegateऔर लागू:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
{
    return !(touch.view is UIControl)
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.