Вы не видите анимацию, воспроизводимую при прокрутке, потому что каждый раз, когда вызывается scrollViewDidScroll
, вы перезапускаете анимацию, вызывая play
. И поскольку эта функция вызывается почти постоянно, пока вы прокручиваете анимацию, у вас нет шансов воспроизвести больше, чем ее первый кадр. Так что это выглядит приостановленным.
При реализации пользовательского элемента управления обновлением необходимо выполнить 3 этапа:
1. Пользователь прокручивает, но обновление еще не было запущено
На этом этапе вы, вероятно, захотите показать прогресс в вашей анимации в зависимости от того, как далеко прокрутил пользователь. Для этого вы вычисляете прогресс в scrollViewDidScroll
и передаете его в свойство LOTAnimationView
animationProgress
.
Чтобы рассчитать этот прогресс, вы должны знать, как далеко пользователь должен прокрутить вниз, пока не будет запущено обновление. По моему опыту, это происходит при contentOffset.y
приблизительно 150
.
2. Обновление активировано
Когда пользователь прокручивает достаточно вниз, .valueChanged
ControlEvent запускается. Когда это происходит, вы запускаете циклическую анимацию, вызывая play()
на LOTAnimationView
3. Обновление сделано
Когда обновление будет завершено, вы звоните endRefreshing()
на свой собственный элемент управления обновлением. Когда это происходит, вы останавливаете анимацию, вызывая stop()
на LOTAnimationView
Посмотрите на этот небольшой пример LottieRefreshControl, который я использую в одном из моих проектов:
import UIKit
import Lottie
class LottieRefreshControl: UIRefreshControl {
fileprivate let animationView = LOTAnimationView(name: "refresh")
fileprivate var isAnimating = false
fileprivate let maxPullDistance: CGFloat = 150
override init() {
super.init(frame: .zero)
setupView()
setupLayout()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateProgress(with offsetY: CGFloat) {
guard !isAnimating else { return }
let progress = min(abs(offsetY / maxPullDistance), 1)
animationView.animationProgress = progress
}
override func beginRefreshing() {
super.beginRefreshing()
isAnimating = true
animationView.animationProgress = 0
animationView.play()
}
override func endRefreshing() {
super.endRefreshing()
animationView.stop()
isAnimating = false
}
}
private extension LottieRefreshControl {
func setupView() {
// hide default indicator view
tintColor = .clear
animationView.loopAnimation = true
addSubview(animationView)
addTarget(self, action: #selector(beginRefreshing), for: .valueChanged)
}
func setupLayout() {
animationView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
animationView.centerXAnchor.constraint(equalTo: centerXAnchor),
animationView.centerYAnchor.constraint(equalTo: centerYAnchor),
animationView.widthAnchor.constraint(equalToConstant: 50),
animationView.heightAnchor.constraint(equalToConstant: 32)
])
}
}
Теперь вам нужно только позвонить updateProgress
на панели управления обновлением с scrollViewDidScroll
:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
refreshControl.updateProgress(with: scrollView.contentOffset.y)
}