Как отменить предыдущую анимацию при срабатывании нового?

Я пишу приложение для камеры и испытываю проблемы с отображением квадрата фокуса, когда пользователь нажимает на экран.

Мой код (быстро):

self.focusView.center = sender.locationInView(self.cameraWrapper)
self.focusView.transform = CGAffineTransformMakeScale(2, 2)
self.focusView.hidden = false

UIView.animateWithDuration(0.5, animations: { [unowned self] () -> Void in
    self.focusView.transform = CGAffineTransformIdentity
}, completion: { (finished) -> Void in
    UIView.animateWithDuration(0.5, delay: 1.0, options: nil, animations: { () -> Void in
        self.focusView.alpha = 0.0
    }, completion: { (finished) -> Void in
            self.focusView.hidden = true
            self.focusView.alpha = 1.0
    })
})

Однако, если использование последовательно нажимает экран, когда предыдущая анимация не заканчивается, старая и новая анимация будет смешиваться, и фокус будет вести себя странно, например, он исчезнет очень быстро.

Может ли кто-нибудь сказать мне, как отменить предыдущую анимацию, особенно предыдущий блок завершения?

Ответ 1

Пользовательский метод removeAllAnimations для остановки анимации
Замените код ниже.

self.focusView.center = sender.locationInView(self.cameraWrapper)
self.focusView.transform = CGAffineTransformMakeScale(2, 2)
self.focusView.hidden = false
self.focusView.layer.removeAllAnimations() // <<====  Solution
UIView.animateWithDuration(0.5, animations: { [unowned self] () -> Void in
    self.focusView.transform = CGAffineTransformIdentity
}, completion: { (finished) -> Void in

    UIView.animateWithDuration(0.5, delay: 1.0, options: nil, animations: { () -> Void in
        self.focusView.alpha = 0.0
    }, completion: { (finished) -> Void in
            self.focusView.hidden = true
            self.focusView.alpha = 1.0
    })
})


Ссылка: ссылка
enter image description here

Ответ 2

В моем случае я добавляю индикатор фокусировки с помощью addSubview().

self.view.addSubview(square)

square - это UIView I, определенный в функции. Поэтому, когда пользователь нажимает экран для фокусировки, эта функция добавит квадрат в subview. И чтобы отменить эту анимацию, когда произойдет следующий щелчок, я просто просто использую функцию removeFromSuperview(), когда эта функция называется им, удаляет вид из своего супервизора, который здесь является фокусом.

filterView.subviews.forEach({ $0.removeFromSuperview() })

Он отличается от метода выше, чтобы удалить анимацию, но удалите subview напрямую.

Ответ 3

В моем случае мне просто нужно было установить значение i, анимированное для конкретного значения.

Например,

 if ([indexPath isEqual:self.currentPlayerOrderIndexPath])
    {
        [UIView animateWithDuration:0.5
                              delay:0.0
                            options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut
                         animations:^{
                             cell.avatarImageV.transform = CGAffineTransformMakeScale(1.15,1.15);
                         }
                         completion:NULL];
    }
    else
    {
        cell.avatarImageV.transform = CGAffineTransformMakeScale(1.0, 1.0);

Ответ 4

Решение @Jageen великолепно, но я работал с анимацией UIStackView и там мне потребовались дополнительные шаги. У меня есть 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)
}