In Swift, I would like to have several calls to UIView.animate
run in series. That is, when one animation finishes, then I would like another animation to continue after, and so on.
The call to UIView.animate
has a Trailing Closure which I am currently using to make a second call to UIView.animate
to occur.
The Problem is: I want to do N separate animations
From the Apple Documentation for UIView.animate
completion
A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be NULL.
Ideally, I would like to iterate over an array of animation duration
s and use in the calls to animate()
For example,
Iterate over an array and apply those parameters for each animation
let duration = [3.0, 5.0, 10.0]
let alpha = [0.1, 0.5, 0.66]
map
to iterate, and hope that it worksUIView
that says animation occur in series?let redBox = UIView()
redBox.backgroundColor = UIColor.red
self.view.addSubview(redBox)
let iterateToAnimate = duration.enumerated().map { (index, element) -> Double in
print(index, element, duration[index])
UIView.animate(withDuration: duration[index], // set duration from the array
animations: { () in
redBox.alpha = alpha[index]
}, completion:{(Bool) in
print("red box has faded out")
})
}
let redBox = UIView()
redBox.backgroundColor = UIColor.red
self.view.addSubview(redBox)
// One iteration of Animation
UIView.animate(withDuration: 1,
animations: { () in
redBox.alpha = 0
}, completion:{(Bool) in
print("red box has faded out")
})
animate
iterations (wish to avoid)// two iterations of Animation, using a trailing closure
UIView.animate(withDuration: 1,
animations: { () in
redBox.alpha = 0
}, completion:{(Bool) in
print("red box has faded out")
}) { _ in // after first animation finishes, call another in a trailing closure
UIView.animate(withDuration: 1,
animations: { () in
redBox.alpha = 0.75
}, completion:{(Bool) in
print("red box has faded out")
}) // 2nd animation
}
If the parameters are few and are known at compile time, the simplest way to construct chained animations is as the frames of a keyframe animation.
If the parameters are not known at compile time (eg your durations are going to arrive at runtime) or there are many of them and writing out the keyframe animation is too much trouble, then just put a single animation and its completion handler into a function and recurse. Simple example (adapt to your own purposes):
var duration = [3.0, 5.0, 10.0]
var alpha = [0.1, 0.5, 0.66] as [CGFloat]
func doTheAnimation() {
if duration.count > 0 {
let dur = duration.removeFirst()
let alp = alpha.removeFirst()
UIView.animate(withDuration: dur, animations: {
self.yellowView.alpha = alp
}, completion: {_ in self.doTheAnimation()})
}
}
you can use UIView.animateKeyframes
UIView.animateKeyframes(withDuration: 18.0, delay: 0.0, options: [], animations: {
UIView.addKeyframe(withRelativeStartTime: 3.0/15.0, relativeDuration: 3.0/15.0, animations: {
self.redBox.alpha = 0
})
UIView.addKeyframe(withRelativeStartTime: 8.0/15.00, relativeDuration: 5.0/15.0, animations: {
self.redBox.alpha = 0.75
})
}) { (completed) in
print("completed")
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.