developer tip

reloadItemsAtIndexPaths 후 UICollectionView 애니메이션 방지

optionbox 2020. 10. 6. 08:05
반응형

reloadItemsAtIndexPaths 후 UICollectionView 애니메이션 방지


UICollectionView는 reloadItemsAtIndexPaths가 호출 된 후 항목을 애니메이션합니다 (애니메이션 페이드).

이 애니메이션을 피할 수있는 방법이 있습니까?

iOS 6


다음을 시도해 볼 수도 있습니다.

UICollectionView *collectionView;

...

[UIView setAnimationsEnabled:NO];

[collectionView performBatchUpdates:^{
    [collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
    [UIView setAnimationsEnabled:YES];
}];

편집하다:

또한 performBatchUpdatesUIView 애니메이션 블록 을 래핑 하면 기본 애니메이션 대신 UIView 애니메이션이 사용되므로 다음과 같이 애니메이션 지속 시간을 0으로 설정할 수 있습니다.

[UIView animateWithDuration:0 animations:^{
    [collectionView performBatchUpdates:^{
        [collectionView reloadItemsAtIndexPaths:indexPaths];
    } completion:nil];
}];

삽입 및 삭제 중에 iOS 7 탄력있는 애니메이션을 사용하려는 경우 매우 멋집니다!


iOS 7 이상을 타겟팅하는 경우 새로운 UIView방법을 사용할 수 있습니다 performWithoutAnimation:. 내부적으로 이것은 여기의 다른 답변 (일시적으로 UIView애니메이션 / 핵심 애니메이션 작업 비활성화 )과 거의 동일하지만 구문은 훌륭하고 깨끗합니다.

특히이 질문에 대해서는 ...

목표 -C :

[UIView performWithoutAnimation:^{
    [self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];


빠른:

UIView.performWithoutAnimation {
    self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}


물론이 원칙은 변경 사항이 애니메이션 되지 않도록하려는 모든 상황에 적용될 수 있습니다 .


UICollectionView는 reloadItemsAtIndexPaths가 호출 된 후 항목을 애니메이션합니다 (애니메이션 페이드).

이 애니메이션을 피할 수있는 방법이 있습니까?

iOS 6

FlowLayout을 사용하고 있다고 가정합니다. 페이드 애니메이션을 제거하려고하므로 다음을 시도하십시오.

import UIKit

class NoFadeFlowLayout: UICollectionViewFlowLayout {

    override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attrs = super.initialLayoutAttributesForAppearingItem(at: itemIndexPath)
        attrs?.alpha = 1.0
        return attrs
    }

    override func finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attrs = super.finalLayoutAttributesForDisappearingItem(at: itemIndexPath)
        attrs?.alpha = 1.0
        return attrs
    }

}

이것은 매우 오래된 질문이므로 더 이상 iOS 6을 타겟팅하지 않을 것입니다. 나는 개인적으로 tvOS 11에서 작업하고 있었고 같은 질문이 있었기 때문에 이것은 같은 문제와 함께 오는 모든 사람들을 위해 여기에 있습니다.


내가 쓴 UICollectionView에 범주를 그냥 할 수 있습니다. 트릭은 다시로드하는 동안 모든 애니메이션을 비활성화하는 것입니다.

if (!animated) {
    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}

[self reloadItemsAtIndexPaths:indexPaths];

if (!animated) {
    [CATransaction commit];
}

Here is a Swift 3 version to performBatchUpdates without animation to a UICollectionView. I found this to work better for me than collectionView.reloadData() because it reduced cell swapping when records were inserted.

func appendCollectionView(numberOfItems count: Int){

        // calculate indexes for the items to be added
        let firstIndex = dataItems.count - count
        let lastIndex = dataItems.count - 1

        var indexPaths = [IndexPath]()
        for index in firstIndex...lastIndex {
            let indexPath = IndexPath(item: index, section: 0)
            indexPaths.append(indexPath)
        }

   UIView.performWithoutAnimation {

        self.collectionView.performBatchUpdates({ () -> Void in
            self.collectionView.insertItems(at: indexPaths)
        }, completion: { (finished) -> Void in

        })
    }
}

- (void)reloadCollectionViewAnimated:(BOOL)animated  {

    if (animated) {
        [self.collectionView performBatchUpdates:^{
            [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
        } completion:^(BOOL finished) {

        }];
    } else {
        [CATransaction begin];
        [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
        [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
        [CATransaction commit];
    }

}

Just to add my $0.02, I tried both versions of the selected answer, and the original way worked better for my purposes. I am working on an infinite scrolling calendar view that allows for a user to enter the calendar at a given week and then swipe back and forth and select individual days for filtering a list.

In my implementation, in order to keep things performant on older devices the array of dates that represent the calendar view has to be kept relatively small which means holding about 5 weeks worth of dates, with the user in the middle at the 3rd week. The issue with using the second approach is, there's a second step where you have to scroll the collection view back to the middle without an animation, which makes for a very jagged appearance for some reason with the blocked base animation.

My Code:

[UIView setAnimationsEnabled:NO];
[self.collectionView performBatchUpdates:^{
    [self.collectionView deleteItemsAtIndexPaths:indexPathDeleteArray];
    [self.collectionView insertItemsAtIndexPaths:indexPathAddArray];

} completion:NULL];
[UIView setAnimationsEnabled:YES];

NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:14 inSection:0];
[self.collectionView scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];

extension UICollectionView {
    func reloadWithoutAnimation(){
        CATransaction.begin()
        CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
        self.reloadData()
        CATransaction.commit()
    }
}

참고URL : https://stackoverflow.com/questions/14094684/avoid-animation-of-uicollectionview-after-reloaditemsatindexpaths

반응형