変更時にUITableViewアニメーションのreloadDataがある


183

2つのモードを持つUITableViewがあります。モードを切り替えると、セクション数とセクションごとのセル数が異なります。理想的には、テーブルが拡大または縮小するときに、クールなアニメーションを実行します。

これが私が試したコードですが、何もしません:

CGContextRef context = UIGraphicsGetCurrentContext(); 
[UIView beginAnimations:nil context:context]; 
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
[UIView setAnimationDuration:0.5]; 

[self.tableView reloadData];
[UIView commitAnimations];

私がこれをどうやってできるかについての考えはありますか?

回答:


400

実際、それは非常に簡単です:

[_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];

ドキュメントから:

このメソッドを呼び出すと、テーブルビューは指定されたセクションの新しいセルをデータソースに要求します。テーブルビューは、古いセルをアニメーション化して、新しいセルの挿入をアニメーション化します。


13
そして、このページのベストアンサーです。
Matthias D

41
最初のセクションのみを再ロードするため、これは完全に正しくはありません。テーブルに複数のセクションがある場合、これは機能しません
Nosrettap

4
データが変更されていない場合、例外が発生する可能性があります。私の答えを
Matej

8
@Nosrettap:tableViewのより多くまたはすべてのセクションをリロードしたい場合は、NSIndexSetをすべてのセクションインデックスで拡張するだけで、更新する必要があります
JonEasy

Swiftバージョン:_tableView.reloadSections(NSIndexSet(index: 0), withRowAnimation: .Fade)ただし、特に、デフォルトの最初のセクションであるセクション0のみが更新されます。
kbpontius 2016

264

あなたは使いたいかもしれません:

Objective-C

[UIView transitionWithView: self.tableView
                  duration: 0.35f
                   options: UIViewAnimationOptionTransitionCrossDissolve
                animations: ^(void)
 {
      [self.tableView reloadData];
 }
                completion: nil];

迅速

UIView.transitionWithView(tableView,
                          duration: 0.35,
                          options: .TransitionCrossDissolve,
                          animations:
{ () -> Void in
    self.tableView.reloadData()
},
                          completion: nil);

スイフト3、4、5

UIView.transition(with: tableView,
                  duration: 0.35,
                  options: .transitionCrossDissolve,
                  animations: { self.tableView.reloadData() }) // left out the unnecessary syntax in the completion block and the optional completion parameter

面倒はありません。:D

UIViewAnimationOptionTransitionsクールな効果のために必要なものを使用することもできます。

  • transitionNone
  • transitionFlipFromLeft
  • transitionFlipFromRight
  • transitionCurlUp
  • transitionCurlDown
  • transitionCrossDissolve
  • transitionFlipFromTop
  • transitionFlipFromBottom

2
これは、テーブルビューの開始/終了状態が大きく異なる場合(および追加/削除するセクションと行を計算するのが複雑になる場合)に役立ちますが、アニメーション化されていないリロードよりも不快感を感じないものを使います。
ベンパッカード、

1
これは、組み込みのメソッドを使用してテーブルビューをリロードするほど良いアニメーションではありませんが、ここで説明したより高い評価のメソッドとは異なり、これは複数のセクションがある場合に機能します。
Mark Bridges

1
残りの部分をすべて試した後、これは私にとって反抗的に完璧です
Lucas Goossen 2014年

1
@MarkBridgesより高い評価の回答は複数のセクションで機能します:)[_tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)] withRowAnimation:UITableViewRowAnimationFade];
lobianco 14

2
@Anthony終了状態のセクションが開始状態よりも多い/少ない場合、機能しません。次に、追加または削除されたセクションを手動で追跡する必要があります。これは非常に面倒です。
ニコロフスキー2014

78

CATransitionクラスを使ってもっと自由を。

フェードだけではなく、動きもできます。


例えば:

(インポートすることを忘れないでくださいQuartzCore

CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.fillMode = kCAFillModeForwards;
transition.duration = 0.5;
transition.subtype = kCATransitionFromBottom;

[[self.tableView layer] addAnimation:transition forKey:@"UITableViewReloadDataAnimationKey"];

などをtypeニーズに合わせて変更しますkCATransitionFade

Swiftでの実装:

let transition = CATransition()
transition.type = kCATransitionPush
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.fillMode = kCAFillModeForwards
transition.duration = 0.5
transition.subtype = kCATransitionFromTop
self.tableView.layer.addAnimation(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()

CATransitionのリファレンス

スウィフト5:

let transition = CATransition()
transition.type = CATransitionType.push
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.fillMode = CAMediaTimingFillMode.forwards
transition.duration = 0.5
transition.subtype = CATransitionSubtype.fromTop
self.tableView.layer.add(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()

これは、単一の行/セクションではなく、テーブル全体をアニメーション化します。
Agos 2013年

@Agosそれでも質問に答えます。「1行だけをリロードする方法」という質問には、のlayerプロパティにアニメーションを適用するなど、まったく異なる答えがありUITableViewCellます。
Matej 2013年

@matejkramny(質問で参照されているように)テーブルが異なる行だけをアニメーション化することを期待していましたが、このメソッドはすべてのテーブルを一度にプッシュします。多分私は何かが足りないのですか?
Agos 2013年

@Agosうーん、それはそうすることになっています。QuartzCoreはビューを直接変更するため、テーブルの半分しか実行できません。テーブルビューからセルを取得し、このアニメーションをそれぞれに適用してみることができます(ただし、機能するかどうかは不明です)
Matej

2
kCATransitionFadeのおかげで魅力のように働きましたありがとう!:)
quarezz

60

私はあなたがあなたのデータ構造を更新することができると信じています、そして:

[tableView beginUpdates];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView endUpdates];

また、「withRowAnimation」はブール値ではなく、アニメーションスタイルです。

UITableViewRowAnimationFade,
UITableViewRowAnimationRight,
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,
UITableViewRowAnimationMiddle

単純なものですが、トロールドキュメントよりもStackOverflowに直接移動して必要なスニペットを取得するのが簡単です。。ありがとう!
Jasper Blues

24

これらの回答はすべて、セクションが1つしかないUITableViewを使用していることを前提としています。

複数のセクションがある状況を正確に処理するには、以下を使用します。

NSRange range = NSMakeRange(0, myTableView.numberOfSections);
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
[myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];

(注:セクションが0を超えていることを確認してください!)

このコードでデータソースを同時に更新しようとすると、NSInternalInconsistencyExceptionが発生する可能性があることにも注意してください。この場合は、次のようなロジックを使用できます。

int sectionNumber = 0; //Note that your section may be different

int nextIndex = [currentItems count]; //starting index of newly added items

[myTableView beginUpdates];

for (NSObject *item in itemsToAdd) {
    //Add the item to the data source
    [currentItems addObject:item];

    //Add the item to the table view
    NSIndexPath *path = [NSIndexPath indexPathForRow:nextIndex++ inSection:sectionNumber];
    [myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationAutomatic];
}

[myTableView endUpdates];

3
セクションの計算については良い点ですが、セクションが1つしかなく、コードに1つずれるエラーがありました。コードの最初の行をNSRange range = NSMakeRange(0、myTableView.numberOfSections);に変更する必要がありました。
Danyal Aytekin 2012

18

これにアプローチする方法は、tableViewに行とセクションを削除および追加するように指示することです

insertRowsAtIndexPaths:withRowAnimation:
deleteRowsAtIndexPaths:withRowAnimation:
insertSections:withRowAnimation:および
deleteSections:withRowAnimation:

UITableViewのメソッド。

これらのメソッドを呼び出すと、テーブルは要求されたアイテムをアニメーション化してアニメーション化し、次にreloadDataをそれ自体で呼び出して、このアニメーション後の状態を更新できるようにします。この部分は重要です。すべてをアニメーション化して、テーブルのdataSourceから返されたデータを変更しない場合、アニメーションの完了後に行が再び表示されます。

したがって、アプリケーションフローは次のようになります。

[self setTableIsInSecondState:YES];

[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];

テーブルのdataSourceメソッドがチェック[self tableIsInSecondState](または何でも)によって正しい新しいセクションと行のセットを返す限り、これは探している効果を実現します。


16

私は上の答えにコメントすることはできませんが、迅速な実装は次のようになります:

self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade)

reloadSectionsの最初の引数に、更新するセクションをいくつでも含めることができます。

ドキュメントから入手可能なその他のアニメーション:https : //developer.apple.com/reference/uikit/uitableviewrowanimation

fade 挿入または削除された1つまたは複数の行は、テーブルビューにフェードインまたはフェードアウトします。

right 挿入された1つまたは複数の行が右からスライドインします。削除された1つまたは複数の行が右にスライドします。

挿入された1つまたは複数の行が左からスライドインします。削除された1つまたは複数の行が左にスライドします。

top 挿入された1つまたは複数の行が上からスライドインします。削除された1つまたは複数の行が上にスライドします。

底部 に挿入された行または行は下からスライド。削除された1つまたは複数の行が下に向かってスライドします。

ケースなし 挿入または削除された行は、デフォルトのアニメーションを使用します。

ミドル テーブルビューは、古いセルと新しいセルを、配置したスペースまたは配置するスペースの中央に配置しようとします。iPhone 3.2で利用できます。

自動 テーブルビューは、適切なアニメーションスタイルを選択します。(iOS 5.0で導入されました。)


1
Swift 4.2の場合:self.tableView.reloadSections([0]、with:UITableView.RowAnimation.fade)
Reefwing

14

@dmarnel回答のSwift 4バージョン:

tableView.reloadSections(IndexSet(integer: 0), with: .automatic)

9

迅速な実装:

let range = NSMakeRange(0, self.tableView!.numberOfSections())
let indexSet = NSIndexSet(indexesInRange: range)
self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)

8

スウィフト4

tableView.reloadSections([0], with: UITableView.RowAnimation.fade)

1

私の場合、テーブルビューにさらに10行追加して(「結果を表示する」タイプの機能のため)、次のようにしました。

  NSInteger tempNumber = self.numberOfRows;
  self.numberOfRows += 10;
  NSMutableArray *arrayOfIndexPaths = [[NSMutableArray alloc] init];
  for (NSInteger i = tempNumber; i < self.numberOfRows; i++) {
    [arrayOfIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
  }
  [self.tableView beginUpdates];
  [self.tableView insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation:UITableViewRowAnimationTop];
  [self.tableView endUpdates];

ほとんどの場合、「self.numberOfRows」の代わりに、通常はテーブルビューのオブジェクトの配列の数を使用します。したがって、このソリューションが適切に機能することを確認するには、 "arrayOfIndexPaths"が挿入される行のインデックスパスの正確な配列である必要があります。このインデックスパスのいずれかに行が存在する場合、コードがクラッシュする可能性があるため、これらのインデックスパスに対してメソッド「reloadRowsAtIndexPaths:withRowAnimation:」を使用して、クラッシュを回避する必要があります。


1

独自のカスタムアニメーションをUITableViewセルに追加する場合は、

[theTableView reloadData];
[theTableView layoutSubviews];
NSArray* visibleViews = [theTableView visibleCells];

可視セルの配列を取得します。次に、カスタムアニメーションを各セルに追加します。

スムーズなカスタムセルアニメーションについては、この要点を確認してください。 https://gist.github.com/floprr/1b7a58e4a18449d962bd


1

Swiftで reloadData()を使用せずにアニメーションを作成するには、次のようにします(バージョン2.2以降)。

tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove ?? 0

// Do your work here
while numOfCellsToRemove > 0 {
    // ...or here, if you need to add/remove the same amount of objects to/from somewhere
    indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
    numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()

アニメーションの終了後にreloadData()を呼び出す必要がある場合は、次のようにCATransactionの変更を受け入れることができます。

CATransaction.begin()
CATransaction.setCompletionBlock({() in self.tableview.reloadData() })
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove.count ?? 0

// Do your work here
while numOfCellsToRemove > 0 {
     // ...or here, if you need to add/remove the same amount of objects to/from somewhere
     indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
     numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
CATransaction.commit()

このロジックは、行を削除する場合に表示されますが、同じ考えが行の追加にも有効です。アニメーションをUITableViewRowAnimation.Leftに変更してきれいにすることも、他の利用可能なアニメーションのリストから選択することもできます。


1
CATransition *animation = [CATransition animation];
animation.duration = .3;
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setDuration:.3];

[[_elementTableView layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"];

[tableView reloadData];

2
期間を.32回設定する理由
2017

1

カスタム期間のセクションだけでなく、すべてのセクションリロードします

カスタム期間を設定するためのユーザーdurationパラメータUIView.animate

UIView.animate(withDuration: 0.4, animations: { [weak self] in
    guard let `self` = self else { return }
    let indexSet = IndexSet(integersIn: 0..<self.tableView.numberOfSections)
    self.tableView.reloadSections(indexSet, with: UITableView.RowAnimation.fade)
})

0

UITableViewSwiftのネイティブアニメーション

行をtableView.performBatchUpdates同時に挿入および削除して、同時に発生するようにします。@iKenndacからの回答に基づいて、次のようなメソッドを使用します。

  • tableView.insertSections
  • tableView.insertRows
  • tableView.deleteSections
  • tableView.deleteRows

例:

 tableView.performBatchUpdates({
   tableView.insertSections([0], with: .top)
 })

これにより、ゼロ位置にセクションが挿入され、上部から読み込まれるアニメーションが表示されます。これにより、cellForRowAtメソッドが再実行され、その位置に新しいセルがないかチェックされます。このように、特定のアニメーションを使用してテーブルビュー全体を再ロードできます。

再:OPの質問、条件付きフラグは、代替テーブルビューステートのセルを表示するために必要でした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.