使用 UIViewPropertyAnimator 依次为 UIView 的 alpha 设置动画
Posted
技术标签:
【中文标题】使用 UIViewPropertyAnimator 依次为 UIView 的 alpha 设置动画【英文标题】:Animating a UIView's alpha in sequence with UIViewPropertyAnimator 【发布时间】:2017-03-23 09:03:37 【问题描述】:我有一个 UIView,我想在 0.5 秒后显示,并在 0.5 秒后再次隐藏,创建一个简单的动画。我的代码如下:
let animation = UIViewPropertyAnimator.init(duration: 0.5, curve: .linear)
self.timerBackground.alpha = 1
let transition = UIViewPropertyAnimator.init(duration: 0.5, curve: .linear)
self.timerBackground.alpha = 0
transition.startAnimation(afterDelay: 0.5)
animation.startAnimation()
当我测试它时,什么都没有发生。我认为这是因为它们同时运行,这意味着它们相互抵消,但这不是“afterDelay”部分应该防止的吗?
如果我单独运行它们,即从隐藏到可见或从可见到隐藏,它可以工作,但是当我尝试按顺序运行它们时,它不起作用。
我的 UIView 不是不透明或隐藏的。
【问题讨论】:
"但这不是 "afterDelay" 部分应该防止的吗?"不。如果你想在动画之后做一些事情,添加一个completion handler到属性动画器。 developer.apple.com/reference/uikit/uiviewpropertyanimator/… 【参考方案1】:您可以使用Timer
,并为您的UIViewPropertyAnimator
object 添加出现/隐藏动画块在每个计时器滴答声中。
这是一个代码库:
@IBOutlet weak var timerBackground: UIImageView!
private var timer: Timer?
private var isShown = false
private var viewAnimator = UIViewPropertyAnimator.init(duration: 0.5, curve: .linear)
override func viewDidLoad()
super.viewDidLoad()
viewAnimator.addAnimations
self.timerBackground.alpha = 1
viewAnimator.startAnimation()
isShown = true
self.timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(self.startReversedAction), userInfo: nil, repeats: true)
func startReversedAction()
// stop the previous animations block if it did not have time to finish its movement
viewAnimator.stopAnimation(true)
viewAnimator.addAnimations (
self.timerBackground.alpha = self.isShown ? 0 : 1
)
viewAnimator.startAnimation()
isShown = !isShown
我已经为 dots jumping 和 ios 10 Animations demo project 实现了非常相似的行为。
请随时查看以获取更多详细信息。
【讨论】:
【参考方案2】:如果你有复杂的动画,使用UIView.animateKeyframes
你会很好地构建你的代码。如果您将使用嵌套在其他完成块中的 UIView 动画,它可能会导致荒谬的缩进级别和零可读性。
这是一个例子:
/* Target frames to move our object to (and animate)
or it could be alpha property in your case... */
let newFrameOne = CGRect(x: 200, y: 50, width: button.bounds.size.width, height: button.bounds.size.height)
let newFrameTwo = CGRect(x: 300, y: 200, width: button.bounds.size.width, height: button.bounds.size.height)
UIView.animateKeyframes(withDuration: 2.0,
delay: 0.0,
options: .repeat,
animations: _ in
/* First animation */
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.5, animations: [weak self] in
self?.button.frame = newFrameOne
)
/* Second animation */
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: [weak self] in
self?.button.frame = newFrameTwo
)
/* . . . */
, completion: nil)
【讨论】:
我同意动画关键帧很棒,但在 Apple 的 UIView 文档页面上他们说Use of these [UIView.animate] methods is discouraged. Use the UIViewPropertyAnimator class to perform animations instead.
在 WWDC 2017 (developer.apple.com/videos/play/wwdc2017-230) 的高级动画会议中,他们介绍了 UIViewPropertyAnimator
,他们还展示了如何通过嵌套调用来使用关键帧动画,以在其中创建关键帧动画UIViewPropertyAnimator
的初始化(参见该视频中的 26:47)。【参考方案3】:
对我有用的是使用 UIViewPropertyAnimators 序列。这是我的代码示例:
let animator1 = UIViewPropertyAnimator(duration:1, curve: .easeIn)
animator1.addAnimations
smallCoin.transform = CGAffineTransform(scaleX: 4, y: 4)
smallCoin.center = center
let animator2 = UIViewPropertyAnimator(duration:1, curve: .easeIn)
animator2.addAnimations
center.y -= 20
smallCoin.center = center
let animator3 = UIViewPropertyAnimator(duration:10, curve: .easeIn)
animator3.addAnimations
smallCoin.alpha = 0
animator1.addCompletion _ in
animator2.startAnimation()
animator2.addCompletion _ in
animator3.startAnimation()
animator3.addCompletion ( _ in
print("finished")
)
animator1.startAnimation()
您甚至可以添加 afterdelay 属性来管理动画的速度。
animator3.startAnimation(afterDelay: 10)
【讨论】:
以上是关于使用 UIViewPropertyAnimator 依次为 UIView 的 alpha 设置动画的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 UIViewPropertyAnimator.fractionComplete 驱动 UIView.transition
使用 UIViewPropertyAnimator 同步动画 CALayer 属性和 UIView
UIViewPropertyAnimator 自动布局完成问题
使用 UIViewPropertyAnimator 为 UILabel textColor 属性设置动画