Подтвердить что ты не робот

Как отменить анимацию на основе блоков UIView?

Я искал множество SO файлов и ссылок Apple, но все же не смог решить свою проблему.

Что у меня:

  • с двумя UIImageViews и с ними 2 UIButtons
  • 2 вида анимации:
    2.1. первый из них масштабируется, затем вниз по каждому изображению, один за другим, только один раз в viewDidLoad 2.2. второй, когда нажата кнопка (которая является настраиваемой кнопкой, скрытой "внутри" каждого UIImageView), она вызывает анимацию соответствующего UIImageView - только один, а не оба (также масштабируется, а затем вниз).
  • Как я пишу для iOS4 +, мне говорят использовать анимации на основе блоков!

Что мне нужно:

Как отменить запуск анимации? Мне удалось отменить все, кроме последнего...:/ Вот мой фрагмент кода:

[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");
                                      }];
            }];
        }];
    }];

Каким-то образом smallLetter UIImageView работает некорректно, при нажатии (через кнопку) bigLetter отменяет анимацию правильно... спасибо заранее:)

EDIT: Я использовал это решение, но все еще имею проблему с уменьшением размера smallLetter UIImageView - не отменяет вообще... .

EDIT2: Я добавил это в начале следующих/предыдущих методов:

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

проблема остается...:/no idea, как прервать последнюю анимацию для букв в цепочке анимации

4b9b3361

Ответ 1

Вы можете остановить все анимации на экране, вызвав:

[view.layer removeAllAnimations];

(Вам нужно будет импортировать среду QuartzCore для вызова методов на view.layer).

Если вы хотите остановить определенную анимацию, а не все анимации, лучше всего использовать CAAnimations явно, а не вспомогательные методы анимации UIView, тогда у вас будет более подробный контроль и можно явно остановить анимацию по имени.

Документацию Apple Core Animation можно найти здесь:

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

Ответ 2

Для iOS 10 используйте UIViewPropertyAnimator для анимации. Он предоставляет методы запуска, остановки и приостановки анимации 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)

Ответ 3

Я добавлю к Nick ответ, что сделать removeAllAnimations гладкой следующей идеей будет очень удобно.

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

Ответ 4

Когда я работаю с анимацией UIStackView, кроме removeAllAnimations() мне нужно установить некоторые значения в начальные значения, потому что removeAllAnimations() может установить их в непредсказуемое состояние. У меня есть stackView с view1 и view2 внутри, и один вид должен быть видимым, а другой скрытым:

public func configureStackView(hideView1: Bool, hideView2: Bool) {
    let oldHideView1 = view1.isHidden
    let oldHideView2 = view2.isHidden
    view1.layer.removeAllAnimations()
    view2.layer.removeAllAnimations()
    view.layer.removeAllAnimations()
    stackView.layer.removeAllAnimations()
    // after stopping animation the values are unpredictable, so set values to old
    view1.isHidden = oldHideView1 //    <- Solution is here
    view2.isHidden = oldHideView2 //    <- Solution is here

    UIView.animate(withDuration: 0.3,
                   delay: 0.0,
                   usingSpringWithDamping: 0.9,
                   initialSpringVelocity: 1,
                   options: [],
                   animations: {
                    view1.isHidden = hideView1
                    view2.isHidden = hideView2
                    stackView.layoutIfNeeded()
    },
                   completion: nil)
}