26

我有一个UITableView正在填充一个NSFetchedResultsController。你可以为UITableView单元格插入自定义动画吗?

在表的初始加载,我想是动画的细胞,但我想多做一点点自定义动画比

[tableView insertRowsAtIndexPaths:withRowAnimation:]; 

允许。具体而言,我想减慢动画并让他们以特定方式从侧面飞入。我一直无法通过UITableViewRowAnimation常量来实现这一点。有没有一种方法可以使用Core Animation来完成我想要的或者我需要在这个特定的实例中使用UIKit动画?

感谢您的帮助!

乔尔

回答

33

NEWEST SOLUTION(2017年12月12日)

添加夫特4.0版本的动画的方法的。它应然后以同样的方式,如下所述溶液来实现:

func animate() { 
    for cell in self.tableView.visibleCells { 
     cell.frame = CGRect(x: self.tableView.frame.size.width, y: cell.frame.origin.y, width: cell.frame.size.width, height: cell.frame.size.height) 
     UIView.animate(withDuration: 1.0) { 
      cell.frame = CGRect(x: 0, y: cell.frame.origin.y, width: cell.frame.size.width, height: cell.frame.size.height) 
     } 
    } 
} 

NEWER SOLUTION(2015年9月5日)

添加夫特2.0版本的动画的方法的。它应该再以同样的方式被实现为下面的解决方案:

func animate() { 
    for cell in self.tableView.visibleCells { 
     cell.frame = CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height) 
     UIView.animateWithDuration(1.0) { 
      cell.frame = CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height) 
     } 
    } 
} 

新的解决方案(2014年9月28日)

我修改了解决一下,以便实施更容易,并使其与iOS8一起工作。所有你需要做的是在你的TableViewController添加此animate方法,并调用它,只要你想它动画(例如,在你重装的方法,但你可以在任何时候调用它):同样

- (void)animate 
{ 
    [[self.tableView visibleCells] enumerateObjectsUsingBlock:^(UITableViewCell *cell, NSUInteger idx, BOOL *stop) { 
     [cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)]; 
     [UIView animateWithDuration:1 animations:^{ 
      [cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)]; 
     }]; 
    }]; 
} 

,改变你喜欢的动画。这个特定的代码会以较慢的速度从右侧开始对单元格进行动画处理。

老办法(2013年6月6日)

您可以通过实现自己的UITableView并重写insertRowsAtIndexPaths方法做到这一点。下面是如何可能看起来像在那里,细胞会从右侧推的例子,真的慢慢地(1级秒钟的动画):

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation 
{ 
    for (NSIndexPath *indexPath in indexPaths) 
    { 
     UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath]; 
     [cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)]; 

     [UIView beginAnimations:NULL context:nil]; 
     [UIView setAnimationDuration:1]; 
     [cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)]; 
     [UIView commitAnimations]; 
    } 
} 

你可以玩的动画自己。这个方法不会被表视图自动调用,所以你必须重写表视图委托中的reloadData方法并自己调用这个方法。

COMMENT

的reloadData方法应该是这个样子:

- (void)reloadData 
{ 
    [super reloadData]; 
    NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; 
    for (int i = 0; i < [_data count]; i++) 
     [indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]]; 
    [self insertRowsAtIndexPaths:indexPaths withRowAnimation:0]; 
} 
+0

致谢!奇迹般有效。 – 2013-03-08 23:32:28

+0

它只是重写'insertRowsAtIndexPaths:withRowAnimation:'方法?当我重写它,然后用'beginUpdates:'和'endUpdates:'方法调用时,应用程序崩溃在'[UITableView _endCellAnimationsWithContext:]' – 2013-06-05 20:46:04

+0

请参阅我的编辑.. – 2013-06-08 11:18:10

8

materik的answer尚未与iOS 7.1 SDK工作对我来说,我已经打电话[self cellForRowAtIndexPath:indexPath];

后得到了零

这里是我的代码在UITableView的子类:

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths 
       withRowAnimation:(UITableViewRowAnimation)animation 
{ 
    [super insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone]; 
    [self endUpdates]; // Populates UITableView with data 
    [self beginUpdates]; 
    for (NSIndexPath *indexPath in indexPaths) { 
     __block UITableViewCell *cell = [super cellForRowAtIndexPath:indexPath]; 
     if (cell) { // If indexPath isn't visible we'll get nil here 
      // Custom animation 
      CGRect frame = cell.frame; 
      frame.origin.x = cell.frame.size.width; 
      cell.frame = frame; 
      frame.origin.x = 0; 
      void (^animationsBlock)() = ^{ 
       cell.frame = frame; 
      }; 
      if ([[UIView class] respondsToSelector: 
       @selector(animateWithDuration:delay:usingSpringWithDamping: 
          initialSpringVelocity:options:animations:completion:)]) { 
       [UIView animateWithDuration:0.3 
             delay:0 
        usingSpringWithDamping:0.5 
         initialSpringVelocity:0 
            options:0 
           animations:animationsBlock 
           completion:NULL]; 
      } else { 
       [UIView animateWithDuration:0.3 
             delay:0 
            options:UIViewAnimationOptionCurveEaseIn 
           animations:animationsBlock 
           completion:NULL]; 
      } 
     } 
    } 
} 
+0

我插入顶部的行,但我正在越来越细胞无[超级cellForRowAtIndexPath:indexPath] .is它,因为它是不可见的,如果是的话那么我该如何做插入动画 – harpreetSingh 2016-06-08 11:20:02

+0

@harpreetSingh抱歉,这是一段时间,因为我在这个项目上工作。在覆盖''[UITableView insertRowsAtIndexPaths:withRowAnimation:]'后你得到'nil'单元吗?无论如何,我建议你尝试从[更新upvoted答案](http:// stackoverflow。com/a/14182059/1226304),如果它不起作用 - 请仅在此问题中创建测试项目并在此处共享 - 包括我在内的某人可能会检查它并帮助您解决此问题。 – derpoliuk 2016-06-09 10:32:58

+0

我有一个修复。动画没有发生,因为我刚刚在它后面调用[tableView reloadData]。删除之后,它像魅力一样工作。感谢好友 – harpreetSingh 2016-06-10 09:21:02

1

使用此:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{ 
     [cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)]; 
      [UIView animateWithDuration:2 animations:^{ 
       [cell setFrame:CGRectMake(100, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)]; 

      }]; 

} 
+3

这种方法的问题是它总是会重新加载可重用的单元格与用户滚动时的动画(不仅用于插入)。 – 2015-09-05 12:41:25

0

雨燕3.0版本马蒂亚斯·埃里克森的回答

func animate() { 
    for cell in tblView.visibleCells { 
     cell.frame = CGRect(x:320, y:cell.frame.origin.y, width:cell.frame.size.width, height:cell.frame.size.height) 
      UIView.animate(withDuration: 1.0) { 
       cell.frame = CGRect(x:0, y:cell.frame.origin.y, width:cell.frame.size.width, height:cell.frame.size.height) 
      } 
    } 
}