programing

UITableView 행 애니메이션 기간 및 완료 콜백

easyjava 2023. 6. 3. 08:49
반응형

UITableView 행 애니메이션 기간 및 완료 콜백

UITableView 행 애니메이션의 기간을 지정하거나 애니메이션이 완료되면 콜백을 받을 수 있는 방법이 있습니까?

제가 하고 싶은 것은 애니메이션이 완료된 후 스크롤 표시기를 깜박이는 것입니다.그 전에 플래시를 하는 것은 아무 효과가 없습니다.지금까지 해결 방법은 0.5초 지연하는 것입니다(기본 애니메이션 기간인 것 같습니다). 즉,

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

우연히 발견했어요.방법은 다음과 같습니다.

목표-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()

karwag의 훌륭한 답변을 확장하면, iOS 7에서 UIView 애니메이션으로 CAT 트랜잭션을 둘러싸면 테이블 애니메이션 기간을 제어할 수 있습니다.

[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 수준에서 다르게 구현될 것입니다.

그건 정말 유용한 속임수야!저는 항상 CAT 트랜잭션 항목을 작성하지 않기 위해 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)
})

적어도 iOS 7에 대해서는 브렌트의 훌륭한 답변을 요약하면, 당신은 이 모든 것을 [UIview animateWithDuration:delay:options:애니메이션:completion:] 통화로 마무리할 수 있습니다.

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

하지만, 저는 EasyInOut 이외의 다른 것에서 기본 애니메이션 곡선을 재정의할 수 없습니다.

여기 카와그의 대답의 스위프트 버전이 있습니다.

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

CollectionView(컬렉션 뷰)이 문제를 해결하기 위해 간단한 확장을 했습니다.

extension UICollectionView {

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

        self.reloadSections(sections)

        CATransaction.commit()
    }

}

요즘 당신이 이것을 하고 싶다면 iOS 11부터 새로운 기능이 있습니다.

- (void)performBatchUpdates:(void (^)(void))updates 
                 completion:(void (^)(BOOL finished))completion;

업데이트 마감 시 beginUpdates()/endUpdates 섹션과 동일한 코드를 배치합니다.그리고 완성은 모든 애니메이션이 끝난 후에 실행됩니다.

표 보기performBatch메소드는 iOS 11부터만 사용할 수 있으며, 다음 확장자를 사용할 수 있습니다.

extension UITableView {
func performUpdates(_ updates: @escaping () -> Void, completion: @escaping (Bool) -> Void) {
        if #available(iOS 11.0, *) {
            self.performBatchUpdates({
                updates()
            }, completion: completion)
        } else {
            CATransaction.begin()
            beginUpdates()
            CATransaction.setCompletionBlock {
                completion(true)
            }
            updates()
            endUpdates()
            CATransaction.commit()
        }
    }
}

Antoine의 답변은 매우 좋지만 UICollectionView에 대한 답변입니다.UITableView에 대한 내용은 다음과 같습니다.

extension UITableView {
    func reloadSections(_ sections: IndexSet, with rowAnimation: RowAnimation, completion: (() -> Void)?) {
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)
        
        self.reloadSections(sections, with: rowAnimation)
        
        CATransaction.commit()
    }
}

다음과 같이 부릅니다.

tableView.reloadSections(IndexSet(0), with: .none, completion: {
    // Do the end of animation thing        
})

tableView가 UIView.animate의 애니메이션 매개 변수를 무시하고 "위에서 아래로" 기본 애니메이션을 사용하여 행을 다시 로드할 때 문제가 발생하는 경우 다음과 같은 이상한 해결책을 발견했습니다.

필요한 작업:

  1. 사일런트 테이블애니메이션 보기
  2. 전환 애니메이션을 대신 사용

예:

let indicesToUpdate = [IndexPath(row: 1, section: 0)]
UIView.transition(with: self.tableView,
                      duration: 0.5,
                      options: [.transitionCrossDissolve,
                                .allowUserInteraction,
                                .beginFromCurrentState],
                      animations: {
                        UIView.performWithoutAnimation {
                            self.tableView.reloadRows(at: indicesToUpdate,
                                                      with: .none)
                        }
                      })

PS: UIView.transition(...)에도 옵션 완료가 있습니다. :)

insertRowsAtIndexPath를 다음과 같이 랩핑할 수 있습니다.

- (void)beginUpdates
- (void)endUpdates

트랜잭션을 수행한 다음 플래시를 수행합니다.

언급URL : https://stackoverflow.com/questions/3832474/uitableview-row-animation-duration-and-completion-callback

반응형