web-dev-qa-db-ja.com

UITableView行アニメーションの継続時間と完了コールバック

UITableView行アニメーションの期間を指定する方法、またはアニメーションが完了したときにコールバックを取得する方法はありますか?

私がやりたいのは、アニメーションが完了した後にスクロールインジケータを点滅させることです。それより前にフラッシュを実行しても、何も実行されません。これまでのところ、私が持っている回避策は0.5秒を遅らせることです(これはデフォルトのアニメーション持続時間のようです)、すなわち:

[self.tableView insertRowsAtIndexPaths:newRows
                      withRowAnimation:UITableViewRowAnimationFade];
[self.tableView performSelector:@selector(flashScrollIndicators)
                     withObject:nil
                     afterDelay:0.5];
95
Daniel Dickison

これに出会ったばかりです。方法は次のとおりです。

Objective-C

[CATransaction begin];
[tableView beginUpdates];
[CATransaction setCompletionBlock: ^{
    // Code to be executed upon completion
}];
[tableView insertRowsAtIndexPaths: indexPaths
                 withRowAnimation: UITableViewRowAnimationAutomatic];
[tableView endUpdates];
[CATransaction commit];

スイフト

CATransaction.begin()
tableView.beginUpdates()
CATransaction.setCompletionBlock {
    // Code to be executed upon completion
}
tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top)
tableView.endUpdates()
CATransaction.commit()
198
karwag

karwag's fine answer を展開すると、iOS 7では、CATransactionをUIView Animationで囲んで、テーブルアニメーションの長さを制御できます。

[UIView beginAnimations:@"myAnimationId" context:nil];

[UIView setAnimationDuration:10.0]; // Set duration here

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    NSLog(@"Complete!");
}];

[myTable beginUpdates];
// my table changes
[myTable endUpdates];

[CATransaction commit];
[UIView commitAnimations];

UIViewアニメーションの継続時間は、iOS 6には影響しません。おそらく、iOS 7のテーブルアニメーションは、UIViewレベルで異なる方法で実装されます。

39
Brent

短縮 Brent's fine answer 、少なくともiOS 7では、これを[UIView animateWithDuration:delay:options:animations:completion:]呼び出しで簡潔にラップできます:

[UIView animateWithDuration:10 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  [self.tableView beginUpdates];
  [self.tableView endUpdates];
} completion:^(BOOL finished) {
  // completion code
}];

ただし、EaseInOut以外の既定のアニメーションカーブをオーバーライドすることはできません。

25
visnu

これは便利なトリックの1つの地獄です!常にCATransactionを記述することを避けるために、UITableView拡張を作成しました。

import UIKit

extension UITableView {

    /// Perform a series of method calls that insert, delete, or select rows and sections of the table view.
    /// This is equivalent to a beginUpdates() / endUpdates() sequence, 
    /// with a completion closure when the animation is finished.
    /// Parameter update: the update operation to perform on the tableView.
    /// Parameter completion: the completion closure to be executed when the animation is completed.

    func performUpdate(_ update: ()->Void, completion: (()->Void)?) {

        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)

        // Table View update on row / section
        beginUpdates()
        update()
        endUpdates()

        CATransaction.commit()
    }

}

これは次のように使用されます。

// Insert in the tableView the section we just added in sections
self.tableView.performUpdate({
            self.tableView.insertSections([newSectionIndex], with: UITableViewRowAnimation.top)

        }, completion: {
            // Scroll to next section
            let nextSectionIndexPath = IndexPath(row: 0, section: newSectionIndex)
            self.tableView.scrollToRow(at: nextSectionIndexPath, at: .top, animated: true)
        })
23
Frédéric Adda

Swift karwag's answer =のバージョン

    CATransaction.begin()
    tableView.beginUpdates()
    CATransaction.setCompletionBlock { () -> Void in
        // your code here
    }
    tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top)
    tableView.endUpdates()
    CATransaction.commit()
23
primulaveris

私にとっては、collectionViewにこれが必要でした。これを解決するために簡単な拡張を行いました。

extension UICollectionView {

    func reloadSections(sections: NSIndexSet, completion: () -> Void){
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)

        self.reloadSections(sections)

        CATransaction.commit()
    }

}
6
Antoine