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