UIButton wewnątrz widoku, który ma UITapGestureRecognizer

Mam widok z UITapGestureRecognizer. Więc kiedy dotknę widoku, nad tym widokiem pojawia się inny widok. Ten nowy widok ma trzy przyciski. Kiedy teraz naciskam jeden z tych przycisków, nie dostaję akcji przycisków,dostaję tylko akcję gestu dotknięcia. Więc nie mogę już używać tych przycisków. Co mogę zrobić, aby Wydarzenia dotarły do tych przycisków? Dziwne jest to, że przyciski nadal są podświetlone.

Nie mogę po prostu usunąć UITapGestureRecognizer po otrzymaniu tego tap. Ponieważ dzięki niemu można również usunąć nowy widok. Oznacza to, że chcę zachowanie jak fullscreen vide controls .

Author: Crashalot, 2010-07-27

11 answers

Możesz ustawić swój kontroler lub widok (w zależności od tego, który z nich utworzy rozpoznawanie gestów)jako delegat UITapGestureRecognizer. Następnie w delegacie możesz zaimplementować -gestureRecognizer:shouldReceiveTouch:. W swojej implementacji możesz sprawdzić, czy dotyk należy do twojego nowego subview, a jeśli tak, poinstruuj rozpoznawacz gestów, aby go zignorował. Coś w stylu:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    // test if our control subview is on-screen
    if (self.controlSubview.superview != nil) {
        if ([touch.view isDescendantOfView:self.controlSubview]) {
            // we touched our control surface
            return NO; // ignore the touch
        }
    }
    return YES; // handle the touch
}
 236
Author: Kevin Ballard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-27 22:29:17

Jako kontynuacja odpowiedzi Casey ' a na Kevina Ballarda:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
        if ([touch.view isKindOfClass:[UIControl class]]) {
            // we touched a button, slider, or other UIControl
            return NO; // ignore the touch
        }
    return YES; // handle the touch
}

To w zasadzie sprawia, że wszystkie typy formantów wejściowych użytkownika, takie jak przyciski, suwaki itp. praca

 152
Author: cdasher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-05 04:14:56

Tutaj znalazłem odpowiedź: link

Możesz również użyć

tapRecognizer.cancelsTouchesInView = NO;
Co uniemożliwia rozpoznawanie kranu jako jedynemu, który wychwytuje wszystkie krany

UPDATE - Michael wspomniał o linku do dokumentacji opisującej tę właściwość: cancelsTouchesInView

 94
Author: ejazz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:51

Jako kontynuację odpowiedzi Kevina Ballarda, miałem ten sam problem i skończyło się na użyciu tego kodu:

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

Ma ten sam efekt, ale będzie to działać na dowolnym UIButton na dowolnej głębokości widoku (mój UIButton miał kilka głębokich widoków, a delegat UIGestureRecognizer nie miał do niego odniesienia.)

 68
Author: Casey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-12 12:01:44

W systemie iOS 6.0 i nowszych domyślne akcje kontrolne zapobiegają nakładaniu się gestów. Na przykład domyślną akcją dla przycisku jest jedno dotknięcie. Jeśli do widoku nadrzędnego przycisku jest dołączony system rozpoznawania gestów za pomocą jednego dotknięcia, a użytkownik dotknie go, metoda akcji przycisku otrzyma Zdarzenie dotykowe zamiast funkcji rozpoznawania gestów. Dotyczy to tylko rozpoznawania gestów, które nakładają się na domyślną akcję kontrolki, która obejmuje:.....

Od API Apple doc

 8
Author: Jagie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-20 10:16:58

Znalazłem inny sposób, aby to zrobić z tutaj . Wykrywa dotyk, czy wewnątrz każdego przycisku, czy nie.

(1) pointInside: withEvent: (2) locationInView:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
       shouldReceiveTouch:(UITouch *)touch {
    // Don't recognize taps in the buttons
    return (![self.button1 pointInside:[touch locationInView:self.button1] withEvent:nil] &&
            ![self.button2 pointInside:[touch locationInView:self.button2] withEvent:nil] &&
            ![self.button3 pointInside:[touch locationInView:self.button3] withEvent:nil]);
}
 7
Author: MindMirror,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:33

Te odpowiedzi były niekompletne. Musiałem przeczytać wiele postów, jak korzystać z tej operacji boolean.

W Twoim *.h file add this

@interface v1ViewController : UIViewController <UIGestureRecognizerDelegate>

W Twoim *.m file add this

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

    NSLog(@"went here ...");

    if ([touch.view isKindOfClass:[UIControl class]])
    {
        // we touched a button, slider, or other UIControl
        return NO; // ignore the touch
    }
    return YES; // handle the touch
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.



    //tap gestrure
    UITapGestureRecognizer *tapGestRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTappedOnce)];
    [tapGestRecog setNumberOfTapsRequired:1];
    [self.view addGestureRecognizer:tapGestRecog];


// This line is very important. if You don't add it then your boolean operation will never get called
tapGestRecog.delegate = self;

}


-(IBAction) screenTappedOnce
{
    NSLog(@"screenTappedOnce ...");

}
 6
Author: Sam B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-18 23:51:17

Oto szybka wersja Kevin Ballard odpowiedź, która mi pomogła:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if (scrollView.superview != nil) {
        if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false }
    }
    return true
}
 3
Author: John Riselvato,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:10

Możesz zatrzymać uitapgesturerecognizer przed anulowaniem innych zdarzeń (takich jak dotknięcie przycisku), ustawiając następującą wartość logiczną:

    [tapRecognizer setCancelsTouchesInView:NO];
 1
Author: Himanshu Mahajan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-17 11:34:52

Jeśli twój scenariusz jest taki:

Masz prosty widok i kilka UIButtons, kontrolki UITextField dodane jako podview do tego widoku. Teraz chcesz zamknąć klawiaturę, gdy dotkniesz gdziekolwiek indziej w widoku, z wyjątkiem elementów sterujących (dodanych podwinięć)

Wtedy rozwiązaniem jest:

Dodaj następującą metodę do kontrolera XYZViewController.m (który ma twój pogląd)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
 1
Author: NaveenRaghuveer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-23 06:22:38

Optymalizując odpowiedź @ cdasher, otrzymujesz

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
       shouldReceiveTouch:(UITouch *)touch 
{
    return ![touch.view isKindOfClass:[UIControl class]];
}
 1
Author: Clay Bridges,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-13 17:03:28