Всегда прокручивая UIScrollView с UIImage - PullRequest
0 голосов
/ 27 июня 2018

У меня есть горизонтальное UIScrollview в моем приложении, которое имеет 1 действительно длинный UIImageView для начала. У меня есть таймер и анимация, чтобы создать иллюзию, что изображение в режиме прокрутки автоматически прокручивается. Как только изображение подходит к концу, я динамически добавляю подобное изображение в представление прокрутки, чтобы оно выглядело так, как будто изображение повторяется.

Вот как я хочу, чтобы они отображались в режиме прокрутки: image1 | image2 | image3 | image4 ...... и эти изображения будут прокручиваться справа налево. Как это работает в приложении Behance для iPhone перед входом в систему.

Вот код, который у меня есть (в раскадровке у меня уже есть вид с прокруткой и один вид UIIMageview).

override func viewDidAppear(_ animated: Bool) {

        Timer.scheduledTimer(timeInterval: 0.6, target: self, selector: #selector(scrollImage), userInfo: nil, repeats: true)
    }

    @objc func scrollImage() {
        offSet.x = offSet.x + CGFloat(20)
        UIView.animate(withDuration: 1.0, animations: {
            self.behanceView.setContentOffset(self.offSet, animated: false)
        })
    }

     func addImagetoScrollView() {
        let imageView = UIImageView(image:UIImage(named:"Landing_Scrollable"))
        print(imageCount*Int(self.behanceView.contentSize.width)+100)
        imageView.frame = CGRect(x:imageCount*Int(self.behanceView.contentSize.width), y: 0, width: 875, height: 502)
        self.behanceView.contentSize = CGSize(width: imageView.bounds.size.width * CGFloat(imageCount), height: imageView.bounds.size.height)
        self.behanceView.addSubview(imageView)
        imageCount+=1
    }

    extension ViewController: UIScrollViewDelegate {
        func scrollViewDidScroll(_ scrollView: UIScrollView) {

            let scrollViewWidth = scrollView.frame.size.width;
            let scrollOffset = scrollView.contentOffset.x;
            print(imageCount*Int(self.behanceView.contentSize.width - scrollViewWidth))
            if scrollOffset >= CGFloat(imageCount*Int(self.behanceView.contentSize.width - scrollViewWidth)) {
                self.addImagetoScrollView()
            }
        }
    }

Но когда я вижу это в действии, он делает что-то странное, и анимация отключается.

Может кто-нибудь, пожалуйста, помогите.

Спасибо,

1 Ответ

0 голосов
/ 27 июня 2018

Я никогда не видел приложение «Behance», но, наверное, вы спрашиваете, как анимировать бесшовное мозаичное фоновое изображение на экране бесконечно, например:

demo

( Узор Эвана Эккарда. )

Я использовал для анимации длительность анимации 1 секунду, но вы, вероятно, хотите, чтобы в реальном приложении она была намного длиннее.

Вы не должны использовать таймер для этого. Базовая анимация может выполнить анимацию за вас, а анимация будет более плавной и эффективной. (Вы можете подумать, что Core Animation выполняет анимацию, поскольку вы используете UIView анимацию, но я считаю, что при анимации представления прокрутки contentOffset не не использует Core Animation, потому что представление прокрутки должно вызывать его делегат scrollViewDidScroll на каждом шаге анимации.)

Вы также не должны использовать представление прокрутки для этого. UIScrollView существует, чтобы позволить пользователю прокручивать. Так как вы не позволяете пользователю прокручивать, вы не должны использовать UIScrollView.

Вот как вы должны настроить фон:

  1. Создание двух идентичных изображений (с номерами 0 и 1), показывающих одно и то же изображение. Убедитесь, что все изображения достаточно велики, чтобы заполнить экран.

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

  3. Просмотр анимированных изображений 0 х transform.translation.x от 0 до -imageView.bounds.size.width. Это заставит его скользить влево точно на его собственную ширину, поэтому, когда анимация достигает своего конца, правый край изображения 0 находится у левого края экрана (и, таким образом, изображение 0 полностью выходит за левый край экрана). ). Установите для анимации repeatCount значение .infinity.

  4. Добавьте ту же анимацию к виду изображения 1. Таким образом, вид изображения 1 появляется на экране, когда вид изображения 0 покидает его, точно покрывая пиксели, отображаемые при анимации вида изображения 0.

Две анимации заканчиваются в одно и то же время. Когда они заканчиваются, вид изображения 1 находится именно там, где вид изображения 0 был в начале. Так как обе анимации настроены на бесконечное повторение, они сразу начинают все сначала. Когда анимация просмотра изображения 0 начинается заново, просмотр изображения 0 мгновенно возвращается в исходное положение, в котором заканчивается просмотр изображения 1. Поскольку оба изображения показывают одно и то же изображение, пиксели на экране не меняются. Это делает цикл анимации бесшовным.

Вот мой код:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        for imageView in imageViews {
            imageView.image = patternImage
            imageView.contentMode = .scaleToFill
            view.addSubview(imageView)
        }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        let bounds = view.bounds

        let patternSize = patternImage.size
        // Scale the image up if necessary to be at least as big as the screen on both axes.
        // But make sure scale is at least 1 so I don't shrink the image if it's larger than the screen.
        let scale = max(1 as CGFloat, bounds.size.width / patternSize.width, bounds.size.height / patternSize.height)
        let imageFrame = CGRect(x: 0, y: 0, width: scale * patternSize.width, height: scale * patternSize.height)

        for (i, imageView) in imageViews.enumerated() {
            imageView.frame = imageFrame.offsetBy(dx: CGFloat(i) * imageFrame.size.width, dy: 0)

            let animation = CABasicAnimation(keyPath: "transform.translation.x")
            animation.fromValue = 0
            animation.toValue = -imageFrame.size.width
            animation.duration = 1
            animation.repeatCount = .infinity
            animation.timingFunction = CAMediaTimingFunction(name: .linear)

            // The following line prevents iOS from removing the animation when the app goes to the background.
            animation.isRemovedOnCompletion = false

            imageView.layer.add(animation, forKey: animation.keyPath)
        }
    }

    private let imageViews: [UIImageView] = [.init(), .init()]
    private let patternImage = #imageLiteral(resourceName: "pattern")

}
...