29

我有一个由 NSFetchedResultsController 填充的 UITableView。

在表格的初始加载中,我希望对单元格进行动画处理,但我想做更多的自定义动画而不是

[tableView insertRowsAtIndexPaths:withRowAnimation:];

允许。具体来说,我想放慢动画的速度,并让它们以特定的方式从侧面飞入。我无法通过 UITableViewRowAnimation 常量来实现这一点。有没有办法使用核心动画来做我想要的,或者我需要在这个特定的实例中坚持使用 UIKit 动画?

谢谢你的帮助!

乔尔

4

4 回答 4

38

最新解决方案 (2017-12-12)

添加Swift 4.0版本的 animate 方法。然后应该以与以下解决方案相同的方式实现它:

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

更新的解决方案 (2015-09-05)

添加 Swift 2.0 版本的 animate 方法。然后应该以与以下解决方案相同的方式实现它:

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-09-28)

我对解决方案进行了一些修改,以使实现更容易并使其与 iOS8 一起使用。您需要做的就是animate在 TableViewController 中添加此方法,并在您希望它动画时调用它(例如,在您的 reload 方法中,但您可以随时调用它):

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

您可以通过实现自己的 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 方法并自己调用此方法。

评论

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];
}
于 2013-01-06T12:25:39.897 回答
8

materik 的回答对我来说不适用于 iOS 7.1 SDK,打电话后我得到了 nil[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];
            }
        }
    }
}
于 2014-04-04T13:46:41.483 回答
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)];

            }];

}
于 2014-09-26T18:48:20.820 回答
0

Swift 3.0版 Mattias Eriksson 的回答

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)
            }
    }
}
于 2017-08-11T13:38:47.517 回答