如何实现类似于Mail的UITableView行动画

时间:2014-06-20 16:51:22

标签: ios objective-c uitableview animation

在Mail中,如果您通过pull to refresh手动刷新邮箱,如果您没有任何新电子邮件,则视图会向上滑动以隐藏微调器,但现有单元格的外观不会更改 - 它们不会完全没有动画。但是,如果您确实有新的电子邮件,那些从顶部开始动画。如果您在刷新之前没有列出任何电子邮件,那么所有单元格都会很好地生成动画。此外,如果您刷新并删除现有的电子邮件,则其消失是动画的,但除了整个表移动以取代已删除的单元格之外,其他单元格都没有动画。我想在我的应用程序中实现同样的行为。

目前,当我第一次获取数据时,它会立即出现在表中而没有任何动画。如果某些数据被删除并且用户手动刷新,则整个表格会立即更新,因此没有动画消失的单元格,它会立即替换为它下面的行。如果单元格已经显示并且刷新导致新数据添加到表格中,则会出现相同的行为 - 它会立即显示。

当我reloadData时,如何为单元格的外观和消失实现动画?但如果它们没有变化,则不会为现有单元设置动画。

我的设置是获取数据,将JSON解析为数据结构(数组或字典),然后调用reloadData,然后cellForRowAtIndexPath从结构中获取数据。当用户刷新时,它会再次执行相同的步骤。

到目前为止,我的尝试都没有成功。我尝试过而不是简单地调用reloadData,而是调用[self.tableView reloadSections:[NSIndexSet indexsetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];,但这只会激活第一部分,并且它总是为其设置动画,即使没有任何数据发生变化。我的另一个尝试也总是激活它:

[self.tableView beginUpdates];
[self.tableView deleteSections:[NSIndexSet indexsetWithIndex:0] withRowAnimation:YES];
[self.tableView insertSections:[NSIndexSet indexsetWithIndex:0] withRowAnimation:YES];
[self.tableView endUpdates];

1 个答案:

答案 0 :(得分:0)

插入行时,保持索引路径插入数组,然后:

[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:arrayOfInsertedIndexPaths withRowAnimation: UITableViewRowAnimationTop];
[self.tableView endUpdates];

我还没有直接确认,但我很确定这会在你现在插入的时候按照你的意愿行事。

编辑 - 行准确的动画将需要有关模型更改的行准确知识。如何获取插入的索引路径取决于您获取数据的方式。在最艰难的情况下,您只需要获得一个新的集合,并需要自己解决已经发生的变化。您的模型对象可能需要实现等价**,因此您可以得出结论,不同的实例应该被视为相同。

**在NSString isEqualToString:中,这是一个等价测试,而不是一个等同测试,因为它的名字可能暗示。

我们正在比较对象本身,而不是行索引,因此了解删除很难,但不比了解插入更难。例如,这是我为NSMutableArray创建的一个类别,它只处理插入(它非常适合电子邮件或其他时间轴类型的应用程序,它们期待新的东西,而不是删除)。

#import "NSMutableArray+Inserts.h"

@implementation NSMutableArray (NSMutableArray_Inserts)

// insert elements of array into the receiver, sorting on a key
// answer an array of index paths where the insertions happened

- (NSArray *)insertFromArray:(NSArray *)array sortedOn:(NSString *)key ascending:(BOOL)ascending {

    // first insert everything from array (preserving uniqueness according to shallow equality)
    for (id newElement in array) {
        NSInteger position = [self indexOfObject:newElement];
        if (position == NSNotFound) [self addObject:newElement];
    }

    // now sort using key
    [self sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:key ascending:ascending]]];

    // now find the insertions using deep equality
    NSMutableArray *answer = [NSMutableArray array];
    for (id newElement in array) {
        NSInteger position = [self indexOfObject:newElement];
        id element = [self objectAtIndex:position];
        if (element == newElement) {
            [answer addObject:[NSIndexPath indexPathForRow:position inSection:0]];
        }
    }    
    return [NSArray arrayWithArray:answer];
}

一些注意事项:1)我懒惰地将索引路径部分硬编码为0.如果您的模型有多个部分,您将要为每个部分调用此部分并添加一个部分参数,以便获得良好的索引路径,2)这个排序的插入功能与我的特定应用程序相关,您可能不需要它,并且可以删除这两个参数并删除自我sortUsing ...行。 3)考虑删除的一种方法是添加一个类似的方法来回答接收器中元素的索引路径而不是传递的数组。