你能为UITableView Cell Inserts做自定义动画吗?

时间:2012-07-07 23:51:35

标签: objective-c cocoa-touch uitableview nsfetchedresultscontroller

我有一个由NSFetchedResultsController填充的UITableView。

在表的初始加载中,我希望单元格可以动画,但我想做一些比自定义动画更多的

[tableView insertRowsAtIndexPaths:withRowAnimation:];

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

感谢您的帮助!

乔尔

4 个答案:

答案 0 :(得分:36)

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

添加animate方法的 Swift 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-09-05)

添加动画方法的Swift 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-09-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)];
        }];
    }];
}

再次,按照自己喜欢的方式更改动画。此特定代码将以较慢的速率从右侧为单元格设置动画。

OLD SOLUTION(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方法并自行调用此方法。

<强> 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];
}

答案 1 :(得分:8)

使用iOS 7.1 SDK,materik answer无法为我工作,在致电[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];
            }
        }
    }
}

答案 2 :(得分: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 :(得分: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)
            }
    }
}