无限期地显示,如:

(Pattern image by Evan Eckard.)
我在演示中使用了1秒的动画持续时间,但是你可能想要一个真正的应用程序更长的持续时间。
你不应该用计时器。核心动画可以为您执行动画,并让它执行动画更平滑和更高效。(您可能认为核心动画正在执行您的动画,因为您正在使用UIView动画,但我相信动画滚动视图的contentOffset做不使用核心动画,因为滚动视图必须调用其代理的scrollViewDidScroll在每个动画步骤中。)
您也不应该为此使用滚动视图。UIScrollView存在以允许用户滚动。既然你不让用户滚动,你就不应该使用ui滚动视图.
以下是设置背景的方法:
创建二相同的图像视图(编号为0和1),显示相同的图像。确保图像视图的大小足以填满屏幕。
将图像视图0的左边缘放在根视图的左边缘。将图像视图1的左边缘置于图像视图0的右边缘。由于每个图像视图的大小足以填满屏幕,因此图像视图1将完全从屏幕的右边缘开始。
动画图像视图0的transform.translation.x从0到-imageView.bounds.size.width.这将使它精确地按自己的宽度向左滑动,因此当动画到达其末端时,图像视图0的右边缘位于屏幕的左边缘(因此图像视图0完全离开屏幕的左边缘)。设置动画的repeatCount到.infinity.
将相同的动画添加到图像视图1。因此,当图像视图0离开时,图像视图1进入屏幕,正好覆盖图像视图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")
}