Пользовательский UIRefreshControl с Лотти - PullRequest
0 голосов
/ 02 ноября 2018

Моя цель - заменить блесну по умолчанию UIRefreshControl на анимацию Лотти.

Моя проблема в том, что анимация не воспроизводится сразу, когда я опускаю свой UICollectionView, чье подпредставление - UIRefreshControl. Анимация воспроизводится только тогда, когда я слегка прокручиваю вниз и делаю паузу пальцем. В тот момент, когда я снова начинаю перемещать позицию прокрутки, он сразу возвращается в исходное начальное состояние, не играя.

Любые рекомендации приветствуются, ниже приведен соответствующий код.

func setupRefreshControl() {
    guard let refreshContents = Bundle.main.loadNibNamed("RefreshControlView", owner: self, options: nil), let refreshView = refreshContents[0] as? RefreshControlView else { return }

    refreshView.frame = refreshControl.frame
    refreshControl.addSubview(refreshView)

    refreshControl.tintColor = UIColor.clear
    refreshControl.backgroundColor = UIColor.clear
    refreshControl.addTarget(self, action: #selector(exampleFunction), for: .valueChanged)      
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    for subview in refreshControl.subviews {
        if let refreshControlView = subview as? RefreshControlView {
            refreshControlView.activityIndicatorControl.animationView.setAnimation(named: "lottieJson")                
            refreshControlView.activityIndicatorControl.animationView.loopAnimation = true
            refreshControlView.activityIndicatorControl.animationView.play()
            break
        } else {
            continue
        }
    }
}

1 Ответ

0 голосов
/ 03 ноября 2018

Вы не видите анимацию, воспроизводимую при прокрутке, потому что каждый раз, когда вызывается 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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...