I have a UITableView that has two modes. When we switch between the modes I have a different number of sections and cells per section. Ideally, it would do some cool anima
To reload all sections, not just one with custom duration.
User duration
parameter of UIView.animate
to set custom duration.
UIView.animate(withDuration: 0.4, animations: { [weak self] in
guard let `self` = self else { return }
let indexSet = IndexSet(integersIn: 0..<self.tableView.numberOfSections)
self.tableView.reloadSections(indexSet, with: UITableView.RowAnimation.fade)
})
CATransition
class.(don't forget to import QuartzCore
)
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.fillMode = kCAFillModeForwards;
transition.duration = 0.5;
transition.subtype = kCATransitionFromBottom;
[[self.tableView layer] addAnimation:transition forKey:@"UITableViewReloadDataAnimationKey"];
Change the type
to match your needs, like kCATransitionFade
etc.
let transition = CATransition()
transition.type = kCATransitionPush
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.fillMode = kCAFillModeForwards
transition.duration = 0.5
transition.subtype = kCATransitionFromTop
self.tableView.layer.addAnimation(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()
Reference for CATransition
let transition = CATransition()
transition.type = CATransitionType.push
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.fillMode = CAMediaTimingFillMode.forwards
transition.duration = 0.5
transition.subtype = CATransitionSubtype.fromTop
self.tableView.layer.add(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()
For Swift 4
tableView.reloadSections([0], with: UITableView.RowAnimation.fade)
I can't comment on the top answer, but a swift implementation would be:
self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade)
you could include as many sections as you want to update in the first argument for reloadSections.
Other animations available from the docs: https://developer.apple.com/reference/uikit/uitableviewrowanimation
fade The inserted or deleted row or rows fade into or out of the table view.
right The inserted row or rows slide in from the right; the deleted row or rows slide out to the right.
left The inserted row or rows slide in from the left; the deleted row or rows slide out to the left.
top The inserted row or rows slide in from the top; the deleted row or rows slide out toward the top.
bottom The inserted row or rows slide in from the bottom; the deleted row or rows slide out toward the bottom.
case none The inserted or deleted rows use the default animations.
middle The table view attempts to keep the old and new cells centered in the space they did or will occupy. Available in iPhone 3.2.
automatic The table view chooses an appropriate animation style for you. (Introduced in iOS 5.0.)
If you want to add your own custom animations to UITableView cells, use
[theTableView reloadData];
[theTableView layoutSubviews];
NSArray* visibleViews = [theTableView visibleCells];
to get an array of visible cells. Then add any custom animation to each cell.
Check out this gist I posted for a smooth custom cell animation. https://gist.github.com/floprr/1b7a58e4a18449d962bd
Animating without reloadData() in Swift can be done like this (as of version 2.2):
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove ?? 0
// Do your work here
while numOfCellsToRemove > 0 {
// ...or here, if you need to add/remove the same amount of objects to/from somewhere
indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
in case you need to call reloadData() after the animation ends, you can embrace the changes in CATransaction like this:
CATransaction.begin()
CATransaction.setCompletionBlock({() in self.tableview.reloadData() })
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove.count ?? 0
// Do your work here
while numOfCellsToRemove > 0 {
// ...or here, if you need to add/remove the same amount of objects to/from somewhere
indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
CATransaction.commit()
The logic is shown for the case when you delete rows, but the same idea works also for adding rows. You can also change animation to UITableViewRowAnimation.Left to make it neat, or choose from the list of other available animations.