2015-02-23 3 views
9

Używam tej animacji podczas interakcji użytkownika, a czasami animacja może zostać uruchomiona ponownie przed zakończeniem animacji. Chciałbym to anulować poprzednią animację i przejść do nowej.UIView animateWithDuration complete has = TAK pomimo anulowania?

[UIView animateWithDuration:duration 
         delay:0 
        options:UIViewAnimationOptionBeginFromCurrentState 
       animations:^{ 
        self.bounds = bounds; 
       } 
       completion:^(BOOL finished) { 
        if (finished) { 
         // Do some cleanup after animating. 
        } 
       }]; 

Wizualnie, to wydaje się działać, ale w moim bloku zakończenia Powiedziano mi, że zakończone w obu przypadkach, co powoduje uruchomienie kodu porządki przedwcześnie. Tak więc blok ukończenia pierwszej animacji jest uruchamiany natychmiast po rozpoczęciu drugiego, zakończony = YES. Spodziewałem się, że ma on skończoną wartość NO, a drugi (po zakończeniu) ma YES.

Czy istnieje sposób sprawdzenia, czy animacja została ukończona, czy została anulowana przez inną?

Sidenote: Próbowałem robić taką samą animację z CABasicAnimation a następnie dostać gotowy = NO po raz pierwszy i YES po raz drugi, więc zachowanie Dostaję wydaje się być specyficzna dla animateWithDuration.

Oto GIF pokazujący powyższy kod w akcji o czasie trwania 10 i blok zakończenia aktualizujący etykietę. Jak widać, finished jest YES każdym razem animacja zostaje wznowiona z wezwaniem animateWithDuration:

Odpowiedz

11

więc zbadać to dalej i myślę, że jest to iOS 8 specyficzna sprawa, ze względu na to, jak animacje są teraz dodatek domyślnie, co oznacza, że ​​animacja będzie nadal i sumują się, zamiast być anulowane.

Podczas moich poszukiwań znalazłem a WWDC session called "Building Interruptible and Responsive Interactions", który mówi o tym. W sesji twierdzą, że wszystkie animacje zakończą się w tym samym czasie, ale tak nie jest w moich testach (zobacz GIF w pytaniu). Zalecane w sesji obejście polega na utrzymywaniu licznika, ile razy rozpoczęła się animacja, a następnie wykonywaniu działań po animacji, gdy licznik osiągnie zero. To jest trochę hacky, ale działa. Oto kod pytanie dostosowane do tego:

// Add this property to your class. 
self.runningAnimations++; 
[UIView animateWithDuration:duration 
         delay:0 
        options:UIViewAnimationOptionBeginFromCurrentState 
       animations:^{ 
        self.bounds = bounds; 
       } 
       completion:^(BOOL finished) { 
        if (--self.runningAnimations == 0) { 
         // Do some cleanup after animating. 
        } 
       }]; 

Oczywiście trzeba osobny licznik dla każdego typu animacji więc może być nieco niechlujny w końcu, ale nie sądzę, istnieje lepszy sposób, chyba zaczniesz bezpośrednio używać CAAnimation.

+0

Dzięki temu pomogło mi naprawić błędy w animacji, ponieważ skończone zawsze jest prawdziwe na iOS 9. – malhal

+0

Właściwie lepszym sposobem jest sprawdzenie granic warstwy prezentacji, aby wiedzieć, czy skończyła się, czy nie. – malhal

+0

Tak też zrobiłem (iOS 9.3, Swift)! Dzięki za pomoc. –

0

Jakie metody próbowałeś anulować animację?

theView_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
[theView_ setBackgroundColor:[UIColor magentaColor]]; 
[self.view addSubview:theView_]; 

[UIView animateWithDuration:10 
       animations:^{ 
        theView_.frame = CGRectMake(200, 200, 50, 50); 
       } completion:^(BOOL finished) { 
        NSLog(@"done : %@", @(finished)); 
        if(finished) { 

        } 
        else { 

        } 
       }]; 

[self performSelector:@selector(cancelAnimation) withObject:nil afterDelay:2]; 

Sposób cancelAnimation jest następujący:

- (void)cancelAnimation { 
    NSLog(@"cancel"); 
    [theView_.layer removeAllAnimations]; 

}

finished powróci false jeśli animacja anulowane.

wiadomości Zaloguj się zgodnie z oczekiwaniami:

2015-02-23 14:13:58.625 TestPrj[47338:6070317] cancel 
2015-02-23 14:13:58.626 TestPrj[47338:6070317] done : 0 
+1

Tak, ale wywołanie funkcji 'removeAllAnimations' natychmiast powoduje przejście widoku do stanu końcowego. Chcę anulować pierwszą animację przy drugim wywołaniu funkcji "animateWithDuration".Drugie wywołanie wyraźnie je anuluje (blok 'completion' jest wywoływany bezpośrednio), ale wartość' finished' to 'YES' zamiast' NO', więc nie mogę odróżnić anulowanej animacji od animacji, która faktycznie skończone. – Blixt

+0

@ Blixt To, co chcesz zaimplementować, to zatrzymanie/wznowienie animacji za pomocą metody animacji bloku. Widziałeś już ten kod http://stackoverflow.com/questions/15119839/uiview-animation-block-pause-both-the-animation-and-completion-? – Ryan

+0

To jest miłe, ale muszę zastąpić animację, ponieważ animacja "bounds" przechodzi do dowolnej pozycji na podstawie danych wprowadzonych przez użytkownika. Czy istnieje sposób na zastąpienie 'toValue' animacji zamiast jej zatrzymywania? – Blixt