你能为UITableView单元格插入做自定义动画吗



我有一个由NSFetchedResultsController填充的UITableView。

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

[tableView insertRowsAtIndexPaths:withRowAnimation:];

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

谢谢你的帮助!

Joel

最新解决方案(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一起工作。你所需要做的就是在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-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];
}

materik的答案对我的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];
            }
        }
    }
}

使用此:

-(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)];
            }];
}

Swift 3.0版本的Mattias Eriksson的Answer

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

最新更新