Несколько анимаций на imageView внутри scrollView

У меня есть UIScrollView внутри которого у меня есть ImageView. Чего я пытаюсь достичь, так это:
— увеличить изображение, чтобы соответствовать полной высоте экрана, когда пользователь нажимает и уменьшить масштаб, когда пользователь нажимает снова,
— автоматически запустить первую анимацию, которая прокручивается в правой части изображения,
— после этого запустите вторую анимацию, которая прокручивается к середине изображения,
— наконец снова запустить анимацию прокрутки в правой части изображения.
Хотелось бы добиться впечатления плавающего на экране изображения. Пользователь не может прокрутить изображение самостоятельно.




Я уже сделал часть с масштабированием, но проблема у меня есть с анимацией. Я пробовал что-то вроде этого, где offset, middleOffset и endOffset являются CGPoints:

override func viewDidLoad() {
        super.viewDidLoad()
        scrollView.delegate = self
        setupGestureRecognizer()
    }

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
        scrollView.panGestureRecognizer.isEnabled = false
        scrollView.pinchGestureRecognizer?.isEnabled = false
    }

fileprivate func updateMinZoomScaleForSize(size: CGSize) {
        let widthScale = size.width / imageView.bounds.width
        let heightScale = size.height / imageView.bounds.height
        let minScale = min(widthScale, heightScale)

        let maxHeightScale = view.frame.height / imageView.bounds.height
        scrollView.maximumZoomScale = maxHeightScale

        scrollView.minimumZoomScale = minScale
        scrollView.zoomScale = minScale
    }

fileprivate func updateConstraintsForSize(size: CGSize) {
        let yOffset = max(0, (size.height - imageView.frame.height) / 2)
        imageViewTopConstraint.constant = yOffset
        imageViewBottomConstraint.constant = yOffset

        let xOffset = max(0, (size.width - imageView.frame.width) / 2)
        imageViewLeadingConstraint.constant = xOffset
        imageViewTrailingConstraint.constant = xOffset

        view.layoutIfNeeded()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        updateMinZoomScaleForSize(size: view.bounds.size)
    }

    func setupGestureRecognizer() {
        let singleTap = UITapGestureRecognizer(target: self, action: #selector(self.handleSingleTap(recognizer:)))
        singleTap.numberOfTapsRequired = 1
        scrollView.addGestureRecognizer(singleTap)
    }

    func handleSingleTap(recognizer: UITapGestureRecognizer) {
        if (scrollView.zoomScale > scrollView.minimumZoomScale) {
            scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
        } else {
            scrollView.setZoomScale(scrollView.maximumZoomScale, animated: true)
        }
    }

func scrollViewDidScroll(_ scrollView: UIScrollView) {

        UIView.animate(withDuration: 1, delay: 0.3, options: [], animations: { 
            scrollView.setContentOffset(offset, animated: false)
        }, completion: { _ in
            UIView.animate(withDuration: 1, delay: 0.3, options: [], animations: {
                scrollView.setContentOffset(middleOffset, animated: false)
            }, completion: { _ in
                UIView.animate(withDuration: 1, delay: 0.3, options: [], animations: {
                    scrollView.setContentOffset(endOffset, animated: false)
                }, completion: nil)
            })
        })
    }

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView
}

func scrollViewDidZoom(_ scrollView: UIScrollView) {
    updateConstraintsForSize(size: view.bounds.size)
}

Однако это не работает. Сначала анимация загружается после увеличения изображения, но затем она останавливается (она не аварийно завершается). Похоже, анимация не закончена, потому что я не могу уменьшить изображение при повторном нажатии.

1 ответ

  1. Хорошо, я обнаружил, что блоки анимации не могут быть внутри scrollViewDidScrollметода делегата. Я помещаю их в handleSingleTapфункцию, а затем он работает так, как должен.