How to ensure UITableView header cell subview with repeating animation continues animating after a reloadData, user scroll, etc? - ios

I have a ViewController with a header cell that is working well, except that one view in the header cell has a repeating animation that should continue animating endlessly when particular conditions are set in the view controller. I can start the animation sometimes successfully in viewDidLoad and restart it in my handler for the .appDidBecomeActive notification. However when the user scrolls or pulls to refresh the tableview data, the animation stops. I did override the scrollViewDidEndDragging & scrollViewDidEndDecelerating methods to restart it, but its not actually reliably restarting the animation. Clues?
UIView.animate(withDuration: 2.0,
delay: 0.0,
options: [.curveEaseInOut, .autoreverse, .repeat, .beginFromCurrentState],
animations: { self.headerCellAnimatedSubview?.alpha = 1.0 },
completion: { _ in self.headerCellAnimatedSubview?.alpha = 0.0 }
)

After some help I found that adding the animation call to the UITableViewHeaderCell class's override of didMoveToWindow the animation will restart after scroll. However as expected I also had to respond to the appDidBecomeActive notification to restart the animation when the app returns fro background.

Related

Animation freeze screen's other objects and scrolling. How to handle mutiple continues animation in same controller

I'm performing a rotation animation in home screen and also added card view and collection in same screen.
Now, All working fine but screen and animation freeze when i move card or scroll collection. It cause problem animation while doing a repeat rotation animation only.
Here is my code which i used for rotation animation.
Also, tried with dispatch queue but it doesn't worked for me.
UIView.animate(withDuration: 5.0, delay: 0.0, options: [.repeat , .autoreverse], animations: { self.Img_Rotate.transform=self.Img_Rotate.transform.rotated(by: .pi - 0.00001)}) { (complete) in }
Is there any best way to handle multiple animations in the same screen or app.
Thanks in advance for help.

First time animating is glitchy

I am animating a view gradientView in/out using the following:
func hideOrShowGradientView(hide: Bool) {
UIView.animate(withDuration: 0.4, animations: {
self.gradientView.isHidden = hide
})
}
This works well, but on the first time, there is no animation. It just appears. On the second and third time it works wonderfully. I've tried calling the animate block on the main thread but no luck there. Why is this animation failing to occur on the first and only first time around? Should I be using another animation method?
Have you tried calling self.view.layoutIfNeeded(). It forces the view and it's subviews to complete any of it's pending animations immediately, which might be interfering with your animation. You can use it like this:
func hideOrShowGradientView(hide: Bool) {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.4, animations: {
self.gradientView.isHidden = hide
self.view.layoutIfNeeded()
})
}
Apple recommends calling layoutIfNeeded() twice, once before the animation block which forces a redraw on the view and it's subviews, and it completes any pending animations on the view without waiting for the next update cycle, and call it the second time inside the animation block to make sure that the animation changes will be applied immediately.
I had too much going on the main thread in the init method, which was being called only on the first time the view was being presented. Moved unnecessary initialization into view did appear

Animation doesnt work - Swift

Everytime I try to implement an animation in my viewDidLoad, it doesn't work. Any suggestions?
UIView.animate(withDuration: 2.0, delay: 0, options:
[.repeat,.autoreverse], animations: {
self.viewpost.transform = CGAffineTransform(rotationAngle: 360)
}, completion: nil)
Just move your animation to ViewDidAppear.
In ViewDidLoad the ViewController will load but is not shown yet. Because of that the animations wont show or may partially show if the animation is longer than the time for the View Controller to Appear after loading.
In ViewDidAppear the ViewController is on the screen so your animations will fully take place
Hope this helps!

Swift - removeAllAnimations() - One animation after the other

So I animated a button to move to a specific point (CGPoint) on the screen when the view loads. I also added a swipeGestureRecogniser to make it that if the user swipes left, than the animation will stop and a new one will start that takes the button to a different CGPoint. I did this by calling the removeAllAnimations() method on the button. The problem is that when the user swipes left, the button finishes the first animation without animating. So it doesn't stop and start the new animation, but rather it jumps to the end of the first animation and then continues to the next animation. Is there a way to stop the first animation and seamlessly start the next?
This is the code:
It's working as expected. At the time you call removeAllAnimations(), there's only one animation to be removed - the second one will be added in first's completion block. So instead of nesting animations, you can try something like that:
// first animation
UIView.animate(withDuration: 5, delay: 0, options: .curveLinear, animations: { /... }, completion: { //... })
// second animation
UIView.animate(withDuration: 5, delay: 5, animations: { /... })

How to recognize tap gesture while a view is animating

Just wondering is there way to have a view recognize tap gestures while it is being animated? I am working on a view that has a cashapelayer line tethered to it. When the user pans the view (pan gesture) the line follows accordingly until the user stops panning. At this point an animation is executed that brings the view back to its original position and the tether layer back as well. Now my only real problem is that while the view and the tether are animating the view doesnt respond to tap gestures…
Anyone know some tricks? I hope my explanation was understandable and thanks in advance!
(if the tethered view concept is not clear there is a free app called discovr apps which will give an example).
I'm assuming that you are using the [UIView animateWithDuration: delay: options: animations: completion:]; method of animating.
If so, you need to pass UIViewAnimationOptionAllowUserInteraction as an option to get the animated view to respond to touches while it is animating.
(Swift 3) Pass .allowUserInteraction option
UIView.animate(withDuration: 0.75, delay: 0.0, options: [.allowUserInteraction], animations: {
// Desired animation(s)
}, completion: { (finished: Bool) in
// Completion
})
You need to set two options - UIViewAnimationOptionAllowUserInteraction and UIViewAnimationOptionAllowAnimatedContent. First lets you interact with views during animation, second forces to redraw views on every frame of animation and not use snapshots of beginning and ending frames.

Resources