Проверьте, находится ли UIView в середине анимации

Есть ли способ узнать, находится ли UIView в середине анимации? Когда я распечатываю объект просмотра во время его движения, я замечаю, что есть запись "анимации":

search bar should end editing: <UISearchBar: 0x2e6240; frame = (0 0; 320 88); text = ''; autoresize = W+BM; animations = { position=<CABasicAnimation: 0x6a69c40>; bounds=<CABasicAnimation: 0x6a6d4d0>; }; layer = <CALayer: 0x2e6e00>>

Когда анимация остановилась, и я распечатал представление, запись "анимации" исчезла:

search bar should end editing: <UISearchBar: 0x2e6240; frame = (0 0; 320 88); text = ''; autoresize = W+BM; layer = <CALayer: 0x2e6e00>>

8 ответов

Решение

UIView имеет слой ( CALayer). Вы можете отправить анимационные ключи к нему, которые предоставят вам массив ключей, которые идентифицируют анимацию, прикрепленную к слою. Я предполагаю, что если есть какие-либо записи, анимация (ы) работает. Если вы хотите копать еще глубже, взгляните на протокол CAMediaTiming, который принимает CALayer. Он делает еще немного информации о текущей анимации.

iOS 9+ метод, работает даже когда layer.animationKeys не содержит ключей:

let isInTheMiddleOfAnimation = UIView.inheritedAnimationDuration > 0

Из документов:

Этот метод возвращает ненулевое значение только в том случае, если вызывается в блоке анимации UIView.

Анимации фактически привязаны к базовой анимации ядра. CALayer учебный класс

Так что я думаю, что вы можете просто проверить myView.layer.animationKeys

Здесь много устаревших ответов. Мне просто нужно было предотвратитьUIView анимация запускалась, если она была запущена в том же представлении, поэтому я создал категорию на UIView:-

extension UIView {

    var isAnimating: Bool {
        return (self.layer.animationKeys()?.count ?? 0) > 0
    }

}

Таким образом, я могу просто проверить статус анимации любого представления следующим образом:-

if !myView.isAnimating {
  UIView.animate(withDuration: 0.4) {
    ...
  }
} else {
  // already animating
}

Это кажется менее хрупким, чем отслеживание с помощью переменной состояния.

Я не уверен в контексте вопроса, но я пытался выяснить, анимировалось ли представление перед запуском второй анимации, чтобы избежать пропуска. Однако есть опция анимации UIView UIViewAnimationOptionBeginFromCurrentState при необходимости анимация будет объединена, чтобы придать плавный вид. Тем самым устраняется моя необходимость знать, был ли вид оживляющим.

Есть загвоздка с трюком animationKeys.

Иногда может быть несколько анимационных клавиш, задерживающихся после завершения анимации.

Это означает, что слой без анимации может возвращать набор animationKeys, даже если он на самом деле не анимируется.

Вы можете убедиться, что animationKeys автоматически удаляются, установив для свойства анимации removeOnCompletion значение YES.

например

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"aPath"];
animation.removedOnCompletion = YES;

Если вы сделаете это для всех анимаций, которые вы применяете к своему слою, это гарантирует, что, когда слой не анимируется, в нем нет анимационных клавиш.

Некоторые из них не сработали для меня. Причина в том, что эти анимации асинхронны.

То, что я сделал, определило свойство

@property BOOL viewIsAnimating;

И в моей анимации

[UIView animateWithDuration:0.25
                 animations:^{
                     viewIsAnimating = YES;
                 } completion:^(BOOL finished) {
                     if (finished) {
                         viewIsAnimating = NO;
                     }
                 }];

Ссылка на вопрос: позиция центра UIView во время анимации

Я сравниваю фрейм представления и layer.presentation()?.frame, чтобы проверить его анимацию. Если leftView находится на пути к завершению, кадр leftView.layer.presentation()?. не равен его кадру:

if self.leftView.layer.presentation()?.frame == self.leftView.frame {
   // the animation finished
} else {
   // the animation on the way
}

Но этот метод может не работать, если представление перемещается в конечную позицию во время анимации. Может потребоваться дополнительная проверка состояния.

Вы можете использовать свойство слоя UIView. CALayer имеет свойство, называемое ключами анимации, вы можете проверить его количество, если оно больше 0.

if (view.layer.animationKeys.count) {

  // Animating

}else {

// No

}

В документации:

-(nullable NSArray<NSString *> *)animationKeys;

Возвращает массив, содержащий ключи всех анимаций, * прикрепленных к получателю в настоящий момент. Порядок массива соответствует порядку *, в котором будут применяться анимации.

Вы можете запросить слой презентации, как предложено здесь. Мой уровень презентации не соответствует слою моей модели, даже если у меня нет анимации

Другие вопросы по тегам