【问题标题】:Ever scrolling UIScrollView with UIImage使用 UIImage 滚动 UIScrollView
【发布时间】:2018-12-05 17:38:20
【问题描述】:

我的应用程序中有一个水平 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()
            }
        }
    }

但是当我看到它在运行时,它会做一些奇怪的事情并且动画全部关闭。

有人可以帮忙吗。

谢谢,

【问题讨论】:

  • 您希望用户能够手动滚动视图吗?还是应该只因为计时器而滚动?
  • 我认为您应该在滚动图像之前将所有图像添加到滚动视图,而不是在 viewDidAppear 中调用滚动图像,顺便说一句,您应该在其函数顶部调用 super.viewDidAppear(animated)
  • @robmayoff :我希望这是一个基于计时器的自动滚动,并且用户交互被禁用。
  • @TungVuDuc :很好。我可以在开始时添加所有图像,这很有效,但我不确定有多少图像会足够好,所以想动态添加它。

标签: ios swift3 uiscrollview


【解决方案1】:

我从未见过“Behance”应用,但我猜你是在问如何在屏幕上无限期地为无缝平铺的背景图像设置动画,如下所示:

(Pattern image by Evan Eckard.)

我在演示中使用了 1 秒的动画持续时间,但您可能希望在真实应用中使用更长的持续时间。

您不应该为此使用计时器。 Core Animation 可以为你执行动画,让它执行动画更流畅,更高效。 (您可能认为 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")

}

【讨论】:

    猜你喜欢
    • 2019-11-16
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多