Reputation: 15
Trying to get the background colours of my popup UIView to change between 4 colours and then loop back and repeat. For the code below, only the last two colours are appearing, the first two are skipping, I've tried everything I can think of, any idea what I'm missing?
UIView.animateWithDuration(2, delay: 0.0, options:[UIViewAnimationOptions.Repeat, UIViewAnimationOptions.Autoreverse], animations: {
self.view.backgroundColor = UIColor.blackColor()
self.view.backgroundColor = UIColor.greenColor()
self.view.backgroundColor = UIColor.grayColor()
self.view.backgroundColor = UIColor.redColor()
}, completion: nil)
Updated code:
UIView.animate(withDuration: 12, delay: 1, options:
[UIViewAnimationOptions.allowUserInteraction,
UIViewAnimationOptions.repeat,
UIViewAnimationOptions.autoreverse],
animations: {
self.popupView.backgroundColor = UIColor.black
self.popupView.backgroundColor = UIColor.green
self.popupView.backgroundColor = UIColor.gray
self.popupView.backgroundColor = UIColor.red
}, completion:nil )
Update 2: Individual animation block:
UIView.animate(withDuration: 3, delay: 0.0, options:
[UIViewAnimationOptions.repeat,
UIViewAnimationOptions.autoreverse,
.allowUserInteraction],
animations: { (BOOL) -> Void in
self.popupView.backgroundColor = UIColor.black
}) { (Bool) -> Void in
UIView.animate(withDuration: 3.0, animations: { () -> Void in
self.popupView.backgroundColor = UIColor.green
}, completion: { (Bool) -> Void in
UIView.animate(withDuration: 3.0, animations: { () -> Void in
self.popupView.backgroundColor = UIColor.gray
}, completion: { (Bool) -> Void in
UIView.animate(withDuration: 3.0, animations: { () -> Void in
self.popupView.backgroundColor = UIColor.white
}, completion:nil)
})
})
}
Upvotes: 0
Views: 610
Reputation: 4884
First of all, color change in animation block will not animate color change. However if you want to just change color, it might be okay to use animation block.
To get a result you want with animation block the code should look like below.
UIView.animate(withDuration: 12, delay: 1, options:
[.allowUserInteraction, .repeat, .autoreverse],
animations: {
self.popupView.backgroundColor = UIColor.black
}, completion:{ competed in
UIView.animate(withDuration: 12, delay: 1, options:
[.allowUserInteraction, .repeat, .autoreverse],
animations: {
self.popupView.backgroundColor = UIColor.green
}, completion: .... )
If you want to just change background color every N seconds, you better use timer.
UDATE
Here's an example of using timer.
class MyViewController : UIViewController {
var timer: Timer?
let colors: [UIColor] = [.white, .black, .red, .magenta]
var idx: Int = 0
deinit {
timer?.invalidate()
timer = nil
}
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer(timeInterval: 5,
target: self,
selector: #selector(changeColor),
userInfo: nil,
repeats: true)
}
@objc
func changeColor() {
view.backgroundColor = colors[idx]
idx = (idx + 1) % colors.count
}
}
Using timer will make your code simpler.
Upvotes: 0
Reputation: 5521
First off, backgroundColor
is not animatable. But if it was, or if you wanted to animate something that is animatable, the better way to cycle through multiple animations would be to use key frame animation, like so:
UIView.animateKeyframes(withDuration: 12, delay: 0, options: [.allowUserInteraction, .repeat, .autoreverse], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.25, animations: {
self.popupView.backgroundColor = .black
})
UIView.addKeyframe(withRelativeStartTime: 0.25, relativeDuration: 0.25, animations: {
self.popupView.backgroundColor = .green
})
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.25, animations: {
self.popupView.backgroundColor = .gray
})
UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25, animations: {
self.popupView.backgroundColor = .red
})
}, completion: nil)
In this case I set the relativeDuration
for each keyFrame to be 0.25 (1/4) of the total animation time, and set the relativeStartTime
to be beginning, 1/4, 1/2, and 3/4 of the way through the total duration.
Again, to reiterate, that is not an animatable property, but this is an effective way to chain animations together.
It also is possible to animate color change by using transition
instead of animate
, though you can't do keyFrame transition. You could chain these together by using the completions, and when you get to the end you'd have to start the animation over again by calling some wrapper function or something similar:
UIView.transition(with: self.popupView, duration: 3, options: .allowUserInteraction, animations: {
self.popupView.backgroundColor = .black
}, completion: { (finished) in
UIView.transition(with: self.popupView, duration: 3, options: .allowUserInteraction, animations: {
self.popupView.backgroundColor = .green
}, completion: { (finished) in
UIView.transition(with: self.popupView, duration: 3, options: .allowUserInteraction, animations: {
self.popupView.backgroundColor = .gray
}, completion: { (finished) in
UIView.transition(with: self.popupView, duration: 3, options: .allowUserInteraction, animations: {
self.popupView.backgroundColor = .red
}, completion: { (finished) in
//Start the chain over again
})
})
})
})
Upvotes: 1