在更改时为UITableView添加一个reloadDataanimation

我有一个UITableView有两种模式。 当我们在不同的模式之间切换时,每个部分有不同数量的部分和单元格。 理想情况下,当表增长或缩小时,它会做一些很酷的animation。

这是我试过的代码,但它什么都不做:

CGContextRef context = UIGraphicsGetCurrentContext(); [UIView beginAnimations:nil context:context]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:0.5]; [self.tableView reloadData]; [UIView commitAnimations]; 

任何想法,我怎么能做到这一点?

其实这很简单:

 [_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 

从文档 :

调用此方法会导致表视图向其数据源请求指定节的新单元格。 表格视图为新的单元插入animation,因为它将旧的单元animation化。

您可能想要使用:

Objective-C的

 [UIView transitionWithView: self.tableView duration: 0.35f options: UIViewAnimationOptionTransitionCrossDissolve animations: ^(void) { [self.tableView reloadData]; } completion: nil]; 

迅速

 UIView.transitionWithView(tableView, duration: 0.35, options: .TransitionCrossDissolve, animations: { () -> Void in self.tableView.reloadData() }, completion: nil); 

Swift 3

 UIView.transition(with: tableView, duration: 0.35, options: .transitionCrossDissolve, animations: { self.tableView.reloadData() }) // left out the unnecessary syntax in the completion block and the optional completion parameter 

没有麻烦。 :d

你也可以使用任何你想要的更酷的效果的UIViewAnimationOptionTransitions

  • TransitionNone
  • TransitionFlipFromLeft
  • TransitionFlipFromRight
  • TransitionCurlUp
  • TransitionCurlDown
  • TransitionCrossDissolve
  • TransitionFlipFromTop
  • TransitionFlipFromBottom

使用CATransition类有更多的自由。

它不限于褪色,但也可以做运动。


例如:

(不要忘记导入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"]; 

更改type以符合您的需求,如kCATransitionFade

在Swift中实现:

 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() 

CATransition参考

我相信你可以更新你的数据结构,然后:

 [tableView beginUpdates]; [tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]; [tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]; [tableView endUpdates]; 

此外,“withRowAnimation”不完全是一个布尔值,而是一个animation风格:

 UITableViewRowAnimationFade, UITableViewRowAnimationRight, UITableViewRowAnimationLeft, UITableViewRowAnimationTop, UITableViewRowAnimationBottom, UITableViewRowAnimationNone, UITableViewRowAnimationMiddle 

所有这些答案都假设您只使用了一个UITableView。

要准确处理您有多个部分的情况,请使用:

 NSRange range = NSMakeRange(0, myTableView.numberOfSections); NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range]; [myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic]; 

(注意:你应该确保你有超过0个部分!)

另外需要注意的是,如果您尝试使用此代码同时更新数据源,则可能会遇到NSInternalInconsistencyException。 如果是这种情况,你可以使用类似于这样的逻辑:

 int sectionNumber = 0; //Note that your section may be different int nextIndex = [currentItems count]; //starting index of newly added items [myTableView beginUpdates]; for (NSObject *item in itemsToAdd) { //Add the item to the data source [currentItems addObject:item]; //Add the item to the table view NSIndexPath *path = [NSIndexPath indexPathForRow:nextIndex++ inSection:sectionNumber]; [myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationAutomatic]; } [myTableView endUpdates]; 

解决这个问题的方法是告诉tableView删除并添加行和段

insertRowsAtIndexPaths:withRowAnimation:deleteRowsAtIndexPaths:withRowAnimation:insertSections:withRowAnimation:deleteSections:withRowAnimation:

UITableView的方法。 当你调用这些方法时,表格会对你请求的项目进/出animation,然后调用reloadData,这样你可以在这个animation之后更新状态。 这一部分是非常重要的 – 如果你animation了一切,但不改变表的dataSource返回的数据,行将在animation完成后再次出现。

所以,你的应用程序stream程将是:

[self setTableIsInSecondState:YES];

[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];

只要你的表的dataSource方法通过检查[self tableIsInSecondState] (或其他)来返回正确的新的部分和行的集合,这将达到你正在寻找的效果。

我不能评论最重要的答案,但快速实施将是:

 self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade) 

您可以在reloadSections的第一个参数中包含尽可能多的部分。

其他animation可从文档: https : //developer.apple.com/reference/uikit/uitableviewrowanimation

淡入插入或删除的一行或多行淡入或淡出表视图。

插入的一行或多行从右侧滑入; 删除的一行或多行向右滑动。

插入的一行或多行从左侧滑入; 删除的一行或多行向左滑动。

顶部插入的一行或多行从顶部滑入; 删除的一行或多行向顶部滑出。

底部插入的一行或多行从底部滑入; 删除的一行或多行向底部滑出。

大小写无插入或删除的行使用默认的animation。

中间表格视图试图保持旧的和新的单元居中在他们已经或将要占据的空间中。 在iPhone 3.2中可用。

自动表格视图为您select适当的animation风格。 (在iOS 5.0中引入)

快速实施:

 let range = NSMakeRange(0, self.tableView!.numberOfSections()) let indexSet = NSIndexSet(indexesInRange: range) self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic) 

在我的情况下,我想添加10行到tableview(“显示更多的结果”types的function),我做了以下几点:

  NSInteger tempNumber = self.numberOfRows; self.numberOfRows += 10; NSMutableArray *arrayOfIndexPaths = [[NSMutableArray alloc] init]; for (NSInteger i = tempNumber; i < self.numberOfRows; i++) { [arrayOfIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]]; } [self.tableView beginUpdates]; [self.tableView insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; 

在大多数情况下,通常使用tableview的对象数组的数量而不是“self.numberOfRows”。 所以为了确保这个解决scheme对你很好,“arrayOfIndexPaths”需要是被插入的行的索引path的精确数组。 如果任何此索引path存在该行,则代码可能会崩溃,因此对于这些索引path应该使用方法“reloadRowsAtIndexPaths:withRowAnimation:”以避免崩溃

如果您想将自己的自定义animation添加到UITableView单元格,请使用

 [theTableView reloadData]; [theTableView layoutSubviews]; NSArray* visibleViews = [theTableView visibleCells]; 

得到一个可见的单元格数组。 然后添加任何自定义animation到每个单元格。

看看我张贴的一个stream畅的自定义单元格animation这个要点。 https://gist.github.com/floprr/1b7a58e4a18449d962bd

Swift中没有reloadData()的animation可以像这样完成(从版本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() 

如果您需要在animation结束后调用reloadData(),则可以像下面这样包含CATransaction中的更改:

 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() 

显示的逻辑是用于删除行的情况,但是同样的想法也适用于添加行。 您也可以将animation更改为UITableViewRowAnimation.Left以使其整齐,或者从其他可用animation的列表中进行select。

 CATransition *animation = [CATransition animation]; animation.duration = .3; [animation setType:kCATransitionPush]; [animation setSubtype:kCATransitionFromLeft]; [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [animation setDuration:.3]; [[_elementTableView layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"]; [tableView reloadData];