NSFetchedResultsControllerによって生成されているUITableViewがあります。
テーブルの初期読み込み時に、セルをアニメーション化したいのですが、
[tableView insertRowsAtIndexPaths:withRowAnimation:];
許可します。具体的には、アニメーションを遅くし、特定の方法で横から飛ばしてもらいたいと思います。 UITableViewRowAnimation定数ではこれを実現できませんでした。 Core Animationを使用して、私がやりたいことを正確に実行する方法はありますか、またはこの特定のインスタンスでUIKitアニメーションに固執する必要がありますか?
助けてくれてありがとう!
ジョエル
最新のソリューション(2017-12-12)
Swift 4.バージョンの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];
}
materikの answer iOS 7.1 SDKでは機能しません。[self cellForRowAtIndexPath:indexPath];
を呼び出した後、nilになりました
これが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.マティアスエリクソンの回答のバージョン
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)
}
}
}