В настоящее время я работаю над анимацией кнопки с помощью различных анимаций в Swift с Lottie.

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

Он сделал это наоборот, чтобы войти в зацикленную анимацию следующим образом:

func animate(animation: Animation?, endIn loop: Animation?) {
    self.setImage(nil, for: .normal)
    self.animationView.isHidden = false
    self.animationView.animation = animation
    self.animationView.loopMode = .playOnce
    self.animationView.play { _ in
        self.animationView.animation = loop
        self.animationView.loopMode = .loop
        self.animationView.play()
    }
}

Возможно, кто-то уже реализовал такой переход, буду признателен за любую помощь в этом.

Изменить: я пытался сделать это таким образом, а затем, когда выборка была завершена, просто вызвал self.animationView.loopMode = .playOnce

func animate(startAnimation: Animation?,
             transitionTo loop: Animation?,
             endAnimation: Animation?,
             image: UIImage?) {
    self.setImage(nil, for: .normal)
    self.animationView.isHidden = false
    self.animationView.animation = startAnimation
    self.animationView.loopMode = .playOnce
    self.animationView.play { _ in
        self.animationView.animation = loop
        self.animationView.loopMode = .loop
        self.animationView.play { _ in
            self.animationView.animation = endAnimation
            self.animationView.loopMode = .playOnce
            self.setImage(image, for: .normal)
        }
    }
}

Изменить 2:

Я нашел работающее, хотя и плохое решение, запустив цикл с помощью верхней функции, а затем вызвав это, чтобы завершить его:

func stopLoopAndTranstion(to animation: Animation?, endIn image: UIImage?) {
    guard let animation = animation else {
        return
    }

    if self.animationView.realtimeAnimationProgress > 0.95 {
        self.animationView.stop()
        self.animationView.animation = animation
        self.animationView.loopMode = .playOnce
        self.animationView.play()
    } else {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
            self.stopLoopAndTranstion(to: animation, endIn: image)
        }
    }
}

Что я здесь делаю, так это проверяю анимациюProgress, и как только она достигает определенного прогресса, я останавливаюсь и заменяю анимацию. Я скорее считаю это взломом, чем решением. Каждый раз, когда я запускаю эту функцию, загрузка ЦП увеличивается на 2-3%, пока анимация не будет заменена. Хотя этими 2-3% можно пренебречь, я еще не удовлетворен и все еще ищу более чистый способ добиться чего-то подобного.

2
Cronay 19 Дек 2019 в 15:09
Ждать оставшейся длительности анимации вместо произвольного времени?
 – 
Wyetro
20 Дек 2019 в 01:08

2 ответа

Вы можете использовать один из play(fromProgress...) API, который предоставляет Lottie.

animationView.play(
    fromProgress: animationView.currentProgress,
    toProgress: 1,
    loopMode: .playOnce,
    completion: { [weak self] completed in
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
            self.stopLoopAndTranstion(to: animation, endIn: image)
        }
    }
)

Это гарантирует, что ваша текущая анимация завершится, и в блоке completion вы сможете выполнить завершающую работу.

6
sabius 26 Сен 2020 в 06:51

Может быть, вам просто нужно установить RepeatCount на 0

0
Newarning 11 Авг 2022 в 13:36