WatchOS background color animation - swift

I'm trying to make a simple animation in WatchKit.
I want to blink the specific color, and then come back to black background. It all works fine... once. After this first blink nothing will happen. I've tried searching but couldn't find relevant answer.
My guess it that I should somehow reset the state of the animation, but couldn't find any way to do that.
This is the code I'm using for the animation:
animate(withDuration: 0.2, animations: {
//set first color
//mainGroup is a WKInterfaceGroup
self.mainGroup.setBackgroundColor(color)
//set back black color
self.mainGroup.setBackgroundColor(UIColor.black)
})

I've researched a bit more. There are no options in animate function in WatchKit, and that is what makes it harder (can't use autoreverse). The solution is not perfect, but it more or less works. You need to first set the desired 'blink' color, and after that animate the transition to black.
self.mainGroup.setBackgroundColor(color)
animate(withDuration: 0.2, animations: {
self.mainGroup.setBackgroundColor(UIColor.black)
})

If you want a more complicated timing, e.g. smooth "in" animation, you can use delayed execution:
animate(withDuration: 0.2) {
self.mainGroup.setBackgroundColor(color)
}
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.21) {
animate(withDuration: 0.2) {
self.mainGroup.setBackgroundColor(.black)
}
}

Related

Pre-Emptive Swift Animation Object Move - Confusing

Good day,
I have a very simple animation function, that drops a button by 200.
However, I discover that before the animation begins, the object is moved up (-) by 200! Therefore, after the animation, the button is back where it started.
I tried to set self.button1.center = self.view.center in viewDidAppear before calling the function.
func dropStep(){
UIView.animate(withDuration: 6, animations: {
self.button1.center.y += 200
}, completion: nil)
}
I expected the animation to start from where it is intended (at the center of the view) and not pre-emptively shifted up by 200 points.
Try,
func dropStep(){
button1.center = self.view.center
UIView.animate(withDuration: 6, animations: {
self.button1.center.y += 200
}, completion: nil)
}
Okay, so I could not genuinely find the reason behind this.
However, this was an app that was used and reused to learn animations, so maybe somehow the object referencing outlets or some sort of hidden reference was messed up, such that the app behaved funny.
Therefore, I created a new app with virtually the same code, and it behaved as expected. Thanks anyway for your help.

How to (repeat) an animation for a WKInterfaceGroup not using images

I have a very simple animation so naturally I'm trying to avoid image sequences and SpriteKit.
I have simply set a WKInterfaceGroup background to green. I want it to fade in and out alpha 1.0 to 0.2 and 0.2 to 1.0 repeatedly. Call it a pulse or whatever you want.
I can fade it out using:
self.animate(withDuration: 1.0) { row.circleBG.setAlpha(0.2) }.
But how to I fade it back in and repeat the entire animation infinitely?
Even if I create separate fade out and fade in functions only the first call gets executed anyway so that doesn't work either. Even if it did work it won't repeat.
The only repeat method I can find requires an image sequence range like this. row.circleBG.startAnimatingWithImages(in: (need image range), duration: 1.0, repeatCount: 100) But I am not using images.
Of course I could use a green circle image and black circle image but that seems so unnecessary and hacky.
Attempted something like this but it actually wouldn't repeat and I need a fadein + fadeout to repeat together as one animation. The pulse fades in/fades out and repeats.
Also I can only access row.ringStatus. buy creating for (index, value) in. I would like to avoid this code repetition.
var pulseTimer: Timer!
pulseTimer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(pulse), userInfo: nil, repeats: true)
#objc func pulse() {
for (index, value) in self.messageObject.enumerated() {
guard let row = messagesTable.rowController(at: index) as? MessageListRowController else { continue }
DispatchQueue.main.async {
row.ringStatus.setBackgroundColor(.green)
row.ringStatus.setAlpha(1.0)
row.ringStatus.setAlpha(0.2)
}
}
}

Stopping and Resetting a CGAffineTransform

I'm trying to write code where when a trigger happens an instance of UIImageView creates a slow "growing" effect with a CGAffineTransform running for 20 seconds.
The issue happens when the trigger happens again before the first transform has completed. Instead of the image resetting back to it's original size, it shrinks exponentially, depending on when the trigger happened during the first transformation.
Here is my current code:
func changeCategoryImage() {
self.categoryPanoramaImageView.transform = CGAffineTransform.identity
UIView.transition(with: self.categoryPanoramaImageView, duration: 0.4, options: .transitionCrossDissolve, animations: {
self.categoryPanoramaImageView.image = self.newPanoramaImage
}) { (done) in
UIView.animate(withDuration: 10, animations: {
self.categoryPanoramaImageView.transform = CGAffineTransform(scaleX: 5.0, y: 5.0)
})
}
}
I was under the impression that CGAffineTransform.identity would reset the image back to it's original size. This is seems to not be the case.
How can I halt and reset the current running transformation in order to start a new one?
I was under the impression that CGAffineTransform.identity would reset the image back to it's original size. This is seems to not be the case.
Correct. It isn't the case. That's not how animations work. You are making a direct change to the underlying view (i.e. the model layer), but the animation is still present (i.e. the presentation layer).
Thus, you are setting the view's transform to the identity, but you are not removing the existing animation. And animations are additive by default. Hence the result you are observing.
Try inserting
self.categoryPanoramaImageView.layer.removeAllAnimations()
as the first line of your function. That way, you will remove the animation and start over from the identity.

turn animation 180 degrees in swift

I am using a curl up animation when swiping up, which makes a card fly away to the top - it works fine. I'd like to use the same animation, but to swipe down, so that the card flies away down. I guess I'd have to somehow turn the swipe up animation 180 degrees. Is that possible?
let views = (frontView: self.frontView, backView: self.frontView)
// set a transition style
let transitionOptions = UIViewAnimationOptions.TransitionCurlUp
UIView.transitionWithView(self.flashCardView, duration: 0.5, options: transitionOptions, animations: {
views.frontView.removeFromSuperview()
self.flashCardView.addSubview(views.frontView)
}, completion: { finished in
// any code entered here will be applied
})
The UIViewAnimationOptions struct has another option that will solve this for you:
let transitionOptions = UIViewAnimationOptions.TransitionCurlDown

Implementing basic animations with tvOS

I'm hoping someone may be able to help me understand why my tvOS animations are not running.
In my code I have a function like this:
func testAnimation() {
clockLabel.alpha = 0.0
UIView.animateWithDuration(1.0, animations: {
self.clockLabel.alpha = 1.0
})
}
I am calling testAnimation() from within my viewDidLoad(), but no animation ever seems to happen.
I've tested with a few different types of animations, from things like position to opacity, but it seems that no animation ever actually runs in the Simulator.
At this time, my app does not have a focus. All I'm trying to do is load a blank UIView with a label in the middle that fades in.
You're trying to animate your UILabel before it has been displayed. Move your animation from viewDidLoad() to viewDidAppear().
I can confirm this behaviour as this happens for me as well. What I did was setting a delay of 0.1 (afterDelay:), and it is "good enough"
On the other hand, what DID actually work was setting a transform for my views. E.g. (objc though):
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(0.5,0.5);
[UIView animateWithDuration: 0.5 animations:^{
_myView.transform = scaleTransform;
} completion: nil]
Maybe it's a bug in tvOS
Try using UIView Animation, like this (Swift):
clockLabel.alpha = 0
UIView.animateWithDuration(0.5, delay: 0.0, options: .Linear, animations: {
self.clockLabel.alpha = 1.0
}, completion: { finished in
// you may add some code here to make another action right after the animation end, or just delete this comment :)
})
This works on our side.