इशारे पहचानकर्ता और बटन कार्रवाई


99

मेरे पास एक दृश्य पदानुक्रम है जो कुछ इस तरह दिखता है:

UIView (A)
UIView > UIImageView
UIView > UIView (B)
UIView > UIView (B) > Rounded Rect Button
UIView > UIView (B) > UIImageView
UIView > UIView (B) > UILabel

मैंने अपने UIView (B) को जेस्चर पहचानकर्ता संलग्न किया है। समस्या यह है कि मुझे सामना करना पड़ रहा है कि मुझे राउंडेड रेक्ट बटन के लिए कोई क्रिया नहीं मिलती है जो कि UIView (B) के अंदर है। सिंगलटैप जेस्चर पहचानकर्ता बटन के टच अप इनसाइड ईवेंट को कैप्चर / ओवरराइड करता है।

मैं इसे कैसे कारगर बना सकता हूं? मैंने सोचा था कि रिस्पोंडर श्रृंखला पदानुक्रम यह सुनिश्चित करेगा कि बटन स्पर्श घटना को वरीयता दी जाएगी, और यह ट्रिगर हो जाएगा! मैं क्या खो रहा हूँ?

यहाँ कुछ संबंधित कोड है:

#pragma mark -
#pragma mark View lifecycle (Gesture recognizer setup)

- (void)viewDidLoad {
    [super viewDidLoad];

    // double tap gesture recognizer
    UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)];
    dtapGestureRecognize.delegate = self;
    dtapGestureRecognize.numberOfTapsRequired = 2;
    [self.viewB addGestureRecognizer:dtapGestureRecognize];

    // single tap gesture recognizer
    UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)];
    tapGestureRecognize.delegate = self;
    tapGestureRecognize.numberOfTapsRequired = 1;
    [tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize];
    [self.viewB addGestureRecognizer:tapGestureRecognize];

    // add gesture recodgnizer to the grid view to start the edit mode
    UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)];
    pahGestureRecognizer.delegate = self;
    pahGestureRecognizer.minimumPressDuration = 0.5;
    [self.viewB addGestureRecognizer:pahGestureRecognizer];

    [dtapGestureRecognize release];
    [tapGestureRecognize release];
    [pahGestureRecognizer release];
}

#pragma mark -
#pragma mark Button actions

- (IBAction)buttonTouchUpInside:(id)sender {
    NSLog(@"%s, %@", __FUNCTION__, sender);
}

#pragma mark -
#pragma mark Gesture recognizer actions


- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"%s", __FUNCTION__);
}

- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"%s", __FUNCTION__);
}

- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer {

    switch (gestureRecognizer.state) {

        case UIGestureRecognizerStateEnded: {
            NSLog(@"%s", __FUNCTION__);

            break;
        }
        default:
            break;
    }
}

सबसे आसान तरीका है cancelsTouchesInView = false
Bagusflyer

जवाबों:


176

"ShouldReceiveTouch" विधि में आपको एक शर्त जोड़ना चाहिए जो कि बटन में स्पर्श होने पर NO लौटेगी।

यह Apple SimpleGestureRecognizers उदाहरण से है।

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

    // Disallow recognition of tap gestures in the segmented control.
    if ((touch.view == yourButton)) {//change it to your condition
        return NO;
    }
    return YES;
}

आशा है कि यह मदद करेगा

संपादित करें

जैसा कि डैनियल ने उल्लेख किया है कि आपको UIGestureRecognizerDelegateइसके लिए काम करना चाहिए ।

शनि


1
आह !!! हां, मैं इस बारे में भूल गया था -Restognizer: shouldReceiveTouch: विधि। मुझे सही दिशा बताने के लिए धन्यवाद। हालांकि यह मेरी समस्या को हल करता है, लेकिन मुझे अभी भी पता नहीं है कि इस मामले में उत्तरदाता पदानुक्रम क्यों काम नहीं कर रहा है। यह शायद होना चाहिए, लेकिन यह एप्पल द्वारा नियंत्रित नहीं किया जा रहा है।
मुस्तफा

2
UIGestureRecognizer व्यवहार को स्पष्ट रूप से "सामान्य" उत्तरदाता श्रृंखला से अलग बताया गया है। यह Apple का एक डिज़ाइन निर्णय है।
सिल्वेन जी।

11
UIGestureRecognizerDelegate प्रोटोकॉल के अनुरूप याद रखें और UIGestureRecognizer के प्रतिनिधि को उस ऑब्जेक्ट पर सेट करें।
डैनियल

2
व्यापक उपयोग के लिए, रमेश या फ्लाइपिग के परीक्षण खंड पर कुछ प्रकार पर विचार करें। मेरे मामले में, उदाहरण के लिए, मैं लाइन के साथ समाप्त हो गया: if ( [touch.view isKindOfClass:[UIControl class]] || [[touch.view superview] isKindOfClass:[UITableViewCell class]] ) {... ध्यान दें कि टेबलव्यू कोशिकाओं को उनके कंटेंट व्यू में "छुआ" मिलता है, जो कि एक निजी वर्ग का सदस्य है, इसलिए हम इसके बजाय पर्यवेक्षी वर्ग की जांच करते हैं।
clozach

जवाब के लिए धन्यवाद! मेरे मामले में, मैं उसी समस्या में भाग गया लेकिन मैंने इसे केवल तब तक खोजा जब तक मैंने वास्तविक डिवाइस में परीक्षण नहीं किया। UIGestureDelegate का उपयोग किए बिना सिम्युलेटर में ऐप चलाना जैसा कि इस उत्तर में इंगित किया गया है, हालांकि गलत तरीके से अपेक्षित है।
लुइस अर्तोला

51

मुझे भी यही समस्या थी, फिर मैंने कोशिश की

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{

    if ([touch.view isKindOfClass:[UIButton class]]) {      //change it to your condition
        return NO;
    }
    return YES;
}

यह अब पूरी तरह से काम कर रहा है ........।


4
मैं केवल याद कियाmyGestureRecognizer.delegate = self;
zero3nna

20

सामान्यतया, हम सभी प्रकार के UIControls में स्पर्श से बचने के लिए प्रतिनिधि विधि का उपयोग करते हैं:

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

नोट: यह जाँच (checkizer.view वर्ग प्रकार की जांच) नहीं करते हैं।


11

यहाँ एक स्विफ्ट 3.0 संस्करण है:

extension UIViewController: UIGestureRecognizerDelegate {

public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    if touch.view is UIButton {
        return false
    }
    return true
}

इसे मत भूलना:

Make your tapper object delegate to self (e.g: tapper.delegate = self)


6

यहाँ एक स्विफ्ट संस्करण है:

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

इसे मत भूलना:

  1. आपको वर्ग के अनुरूप बनाते हैं UIGestureRecognizerDelegate
  2. आत्म करने के लिए अपने टेपार वस्तु प्रतिनिधि बनाओ (जैसे: tapper.delegate = self)

5

सबसे अच्छा समाधान नीचे कोड स्निपेट का उपयोग करके मेरे दिमाग में है:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint touchLocation = [touch locationInView:self.view];
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.