UITableView animation that starts quickly and slows down by the end - ios

I am programatically scrolling the table with animation. I want this scrolling to be same as the user scrolling (fast at beginning and slow at end). How to perform an animation that start with speed and then go slow in the end?

You can basically use animation block with UIViewAnimationOptions.curveEaseOut of the scrollView / tableView.
curveEaseOut (From documentation):
An ease-out curve causes the animation to begin quickly, and then slow
as it completes.
UIView.animate(withDuration: 0.5, delay: 0.0, options: [.curveEaseOut], animations: {
self.tableView.setContentOffset(CGPoint(0, 100), animated: false)
}, completion: nil)
That way you control over the animation duration and manner.

Related

Slot machine animation using UITableView

I need to implement slot-machine animation according to provided design and timings.
It should perform infinite scroll, until some event will be triggered. After that animation, it should slow down and stop on defined position
For this task I have used next solution:
UITableView with fixed-height cell. It is the same cell with the only difference - icon or text (depends on indexPath.row)
Scroll is only down-to-up that's why I'm using last cell as start point in resetScrollPosition method
If first element reached, scroll position resets to start point
Animation performed as contentOffset change with linear option. In completion block, if animation is still needed, it's called again. If don't needed - slowing animation with easeOut option started
var isRolling: Bool = false
func startScroll() {
isRolling = true
UIView.animate(
withDuration: 0.05,
delay: 0,
options: .curveLinear,
animations: {
self.tableView.contentOffset.y -= self.rowHeight
},
completion: { _ in
if self.isRolling {
self.startScroll()
} else {
self.resetScrollPosition
UIView.animate(
withDuration: 0.7,
delay: 0,
options: .curveEaseOut,
animations: {
self.tableView.contentOffset.y -= 8 * self.rowHeight
},
completion: nil
)
}
})
}
private func resetScrollPosition() {
tableView.reloadData()
tableView.contentOffset.y = startOffset
tableView.reloadData()
}
func stopScroll() {
isRolling = false
}
The problems:
After calling resetScrollPosition, in animations completion block, tableviews contentOffset.y value is updated but tableView stays on the same position. I have tried to change direct contentOffset changing to setContentOffset, scrollToRow, scrollToRect, wrap it in main queue - no changes
Slowing animation should scroll 8 items. It's performed but first 6 items aren't visible during animation, only the last two.
Check the issue gif (jump 2 -> 11 is ok):
Replaced UITableView with UIScrollView
Uploaded code to gist - https://gist.github.com/OlesenkoViktor/76845c5448b421ead0a2303af2b1161d
Thanks #Paulw11 for his idea

How to avoid an animation to disable touch interaction (scroll, swipe, etc)

Im trying to make an animation over a view in my ViewController.
My problem is that the scroll/swipe gestures over other elements like UITableViewControllers or UIPageViewControllers get disabled until the animation finishes.
How can I avoid this behaviour?
Do your animations using allowUserInteraction option:
UIView.animate(withDuration: duration, delay: 0, options: .allowUserInteraction,
animations: {
// Your animations here
},
completion: nil
)

Can all constraints in swift 3 be animated?

I want to animate a view like using the following code:
UIView.animate(withDuration: 2.7, delay: 0.1, options: .allowAnimatedContent, animations: {
self.AVCenterY.constant = 0.8
}, completion: nil)
But it happens so fast it seems like it is not animated. On the other hand, when I animate the property alpha it is animated (it takes the 2.7 seconds to change). I used 2.7 sec to make sure the problem was that I was using a small duration time.
Constraints cannot be animated at all. It is the act of layout that can be animated:
UIView.animate(withDuration: 2.7, delay: 0.1, options: .allowAnimatedContent, animations: {
self.AVCenterY.constant = 0.8
theView.superview?.layoutIfNeeded() // *
}, completion: nil)
When we animate the act of layout (or when the runtime does so), then any constraint changes are also automatically animated.
Note that what I animate is the layout of the superview of the view that is to move. I called it theView but that is just something I made up. You will need an outlet to that view so that you can get its superview, and use the name of that outlet.

withRowAnimation effect disappears if user scrolls Swift

I'm facing a bugging issue concerning the insertRowsAtIndexPaths function and precisely it's withRowAnimation parameter.
With the help of the stack community i've been able to modify the effect of insertion from fast fade to a longer fade (by overriding the function), but the whole effect completely disappears if i scroll the table view upwards, hide the cells from the view and scroll back again.
Because the cells are being reused the effect is rendered totally useless.
I've tried using scrollToRowAtIndexPath function (doesn't work in this case - it initiates after the cells have already loaded, only then it scrolls down and the effect has already gone away) as well as setting the content offset to tableView.contentSize.height - the result is somewhat satisfactory, but again doesn't prevent vanishing of the insertion effect when the user scrolls.
Also willDisplayCell is not an option, because it animates the cell every single time the user scrolls and i need the animation to run just once. Urrgh)
So far i'm out of ideas of how to prevent this issue from happening.
UPDATE:
Added the suclass code
class CustomTable: UITableView{
override func insertRowsAtIndexPaths(indexPaths: [NSIndexPath], withRowAnimation animation: UITableViewRowAnimation) {
self.endUpdates()
self.beginUpdates()
for indexPath:AnyObject in indexPaths{
let cell:UITableViewCell? = (super.cellForRowAtIndexPath(indexPath as! NSIndexPath));
if cell != nil {
cell!.alpha = 0
let animationBlock = { () -> Void in
cell!.alpha = 1;
}
if UIView.respondsToSelector(Selector("animateWithDuration(duration: , delay: , usingSpringWithDamping dampingRatio: , initialSpringVelocity velocity: , options: , animations: , completion: ")){
UIView.animateWithDuration(3, delay: 3.0, usingSpringWithDamping: 1.5, initialSpringVelocity: 0.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: animationBlock, completion: nil)
}else{
UIView.animateWithDuration(3.3, delay: 5.0, options:UIViewAnimationOptions.TransitionCrossDissolve, animations: animationBlock, completion: nil)
}
}
}
}
}

Interrupt and reset UIScrollView animation from UIView.animateWithDuration

I am making a Karaoke app that a user needs to be able to start-over by pressing a button.
I have a UIScrollView that contains a large block of text in a UITextView.
I am using UIView.animateWithDuration to scroll the text for a certain duration. I need to be able to interrupt/stop the animation and reset it back to the beginning.
Unfortunately, for me, whenever I stop the animation, the UITextView disappears and I can't seem to re-add it.
let bottomOffset:CGPoint = CGPoint(x: 0, y: self.textView.frame.size.height)
UIView.animateWithDuration(NSTimeInterval(duration),
delay: NSTimeInterval(0.0) ,
options: UIViewAnimationOptions.CurveLinear,
animations: {
self.scrollView.setContentOffset(bottomOffset, animated: false)
},
completion: { finished in
reset()
}
)
I am stopping the animation by calling:
UIView.animateWithDuration(0.0, animations: {
self.scrollView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 0, height: 0), animated: true)
})
I need to figure out how to:
Stop the animation
Keep the UITextView visible
Scroll the UIScrollView back to the top
Start scrolling again
My codebase is in Swift, but I will gladly accept answers in Objective-C.

Resources