Como cancelar a animação baseada em bloco UIView?

86

Pesquisei um monte de coisas de SO e referências da Apple, mas ainda não consegui gerenciar meu problema.

O que eu tenho:

  1. Uma tela com 2 se UIImageView2 UIButtons conectada a eles
  2. 2 tipos de animação:
    1. Aumentar e diminuir cada imagem, uma após a outra, apenas uma vez em viewDidLoad
    2. Quando um botão é pressionado (um botão personalizado escondido 'dentro' de cada um UIImageView), ele dispara a animação apropriada UIImageView- apenas um, não ambos - (também aumenta e depois diminui).
    3. Como estou escrevendo para iOS4 +, recebo instruções para usar animações baseadas em blocos!

O que eu preciso:

Como cancelo uma animação em execução? Afinal, consegui cancelar, menos o último ...: /

Aqui está meu snippet de código:

[UIImageView animateWithDuration:2.0 
                               delay:0.1 
                             options:UIViewAnimationOptionAllowUserInteraction 
                          animations:^{
        isAnimating = YES;
        self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 2.0, 2.0);
    } completion:^(BOOL finished){
        if(! finished) return;
        [UIImageView animateWithDuration:2.0 
                                   delay:0.0 
                                 options:UIViewAnimationOptionAllowUserInteraction 
                              animations:^{
            self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 0.5, 0.5);
        } completion:^(BOOL finished){
            if(! finished) return;
            [UIImageView animateWithDuration:2.0 
                                       delay:0.0 
                                     options:UIViewAnimationOptionAllowUserInteraction 
                                  animations:^{
                self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 2.0, 2.0);
            } completion:^(BOOL finished){
                if(! finished) return;
                [UIImageView animateWithDuration:2.0 
                                           delay:0.0 
                                         options:UIViewAnimationOptionAllowUserInteraction 
                                      animations:^{
                    self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 0.5, 0.5);
                }
                                      completion:^(BOOL finished){
                                          if (!finished) return;
                                          //block letter buttons
                                          [self.bigLetterButton setUserInteractionEnabled:YES];
                                          [self.smallLetterButton setUserInteractionEnabled:YES];
                                          //NSLog(@"vieDidLoad animations finished");
                                      }];
            }];
        }];
    }];

De alguma forma o smallLetter UIImageViewnão está funcionando corretamente, porque quando pressionado (através do botão) bigLetterestá cancelando as animações corretamente ...

EDIT: Eu usei esta solução, mas ainda estou tendo problemas com a redução smallLetter UIImageView- não cancelando nada ... solução

EDIT2: Eu adicionei isso no início dos métodos next / anterior:

- (void)stopAnimation:(UIImageView*)source {
    [UIView animateWithDuration:0.01
                          delay:0.0 
                        options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction)
                     animations:^ {
                         source.transform = CGAffineTransformIdentity;
                     }
                     completion:NULL
     ];
}

o problema permanece ...: / não faço ideia de como interromper a última animação de letras na cadeia de animação

Raistlin
fonte
Ei, eu acho que a resposta de Hari Kunwar deve ser aceita agora.
marczellm
Hoje em dia, você deve usar UIViewPropertyAnimator - é extremamente mais fácil, também.
Fattie

Respostas:

151

Você pode interromper todas as animações em uma visualização chamando:

[view.layer removeAllAnimations];

(Você precisará importar a estrutura QuartzCore para chamar métodos em view.layer).

Se você deseja interromper uma animação específica, não todas as animações, sua melhor aposta é usar CAAnimations explicitamente em vez dos métodos auxiliares de animação UIView; então, você terá um controle mais granular e poderá interromper as animações explicitamente por nome.

A documentação do Apple Core Animation pode ser encontrada aqui:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html

Nick Lockwood
fonte
10
Só quero adicionar, em minha própria observação, o animateWithDuration subsequente não funciona mais depois de chamar removeAllAnimations. Isso é para fazer paginação e puxar para atualizar os controles, talvez outra pessoa possa observar algo diferente. Acabo usando CABasicAnimation e chamando [myView.layer removeAnimationForKey: @ "animationKey"];
Zhang
Obrigado pela dica @Nick - apenas para avisar que o link não parece mais ser compatível, tente este: developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
trdavidson
52

Para iOS 10, use UIViewPropertyAnimator para animar. Ele fornece métodos para iniciar, parar e pausar animações UIView.

 let animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeOut){
        self.view.alpha = 0.0
 }
 // Call this to start animation.
 animator.startAnimation()

 // Call this to stop animation.
 animator.stopAnimation(true)
Hari Kunwar
fonte
3

Eu acrescentaria à resposta de Nick que, para tornar a próxima ideia fácil de removeAllAnimations, seria muito útil.

[view.layer removeAllAnimations];
[UIView transitionWithView:self.redView
                  duration:1.0f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
                      [view.layer displayIfNeeded];
                  } completion:nil];
Gaston Morixe
fonte
0

Você pode tentar isso (em Swift):

UIView.setAnimationsEnabled(false)
UIView.setAnimationsEnabled(true)

Nota: você pode colocar um código entre essas duas chamadas, se necessário, por exemplo:

UIView.setAnimationsEnabled(false)
aview.layer.removeAllAnimations() // remove layer based animations e.g. aview.layer.opacity
UIView.setAnimationsEnabled(true)
iAmcR
fonte