पुनः लोड करने के बाद UICollectionView के एनिमेशन से बचें। AAndIndexPaths


91

पुन: लोड करने के बाद UICollectionView चेतन आइटम। aAndIndexPaths (फीका एनीमेशन) कहा जाता है।

क्या इस एनीमेशन से बचने का कोई तरीका है?

iOS 6

जवाबों:


231

यह ध्यान देने योग्य है कि यदि आप iOS 7 और इसके बाद के संस्करण को लक्षित कर रहे हैं, तो आप नई UIViewविधि का उपयोग कर सकते हैं performWithoutAnimation:। मुझे संदेह है कि हुड के तहत यह यहाँ के अन्य उत्तरों (अस्थायी रूप से UIViewएनिमेशन / कोर एनिमेशन क्रियाओं को अक्षम करने ) के समान है, लेकिन वाक्यविन्यास अच्छा और साफ है।

तो इस प्रश्न के लिए विशेष रूप से ...

उद्देश्य सी:

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


स्विफ्ट:

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


बेशक यह सिद्धांत किसी भी स्थिति के लिए लागू किया जा सकता है जिसे आप सुनिश्चित करना चाहते हैं कि कोई बदलाव एनिमेटेड नहीं है


3
इसने iOS 7+ पर मेरे लिए स्वीकृत उत्तर से बेहतर काम किया।
फिलिप सबौरिन

यह न केवल संग्रह दृश्य के लिए सभी एनिमेशन को निष्क्रिय करता है
user2159978

10
@ user2159978 यह सही है; यहाँ सभी उत्तर अस्थायी रूप से UIView एनिमेशन को निष्क्रिय कर देते हैं। पारित किए गए ब्लॉक के भीतर से शुरू किए गए कार्यों के लिए एनिमेशन केवल अक्षम हैं, इस मामले में सिर्फ संग्रह दृश्य का पुनः लोड है। यह पूछे जाने वाले प्रश्न का पूरी तरह से मान्य उत्तर है, इसलिए मुझे नहीं लगता कि यह एक डाउन वोट का हकदार है।
22

अविश्वसनीय समाधान। चेतन के बजाय इसका उपयोग करते हुए: अवधि: 0 बिना किसी आइटम के स्व-आकार संग्रह दृश्य कोशिकाओं का उपयोग करते समय एक त्वरित लेकिन दृश्यमान लेआउट गड़बड़ को रोकता है
एथन गिल

1
यह समाधान iOS 14 पर अब काम नहीं करता है, इस ब्लॉक के अंदर मैं
पुनः लोडडाटा का

161

आप यह भी आज़मा सकते हैं:

UICollectionView *collectionView;

...

[UIView setAnimationsEnabled:NO];

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

संपादित करें:

मैंने यह भी पाया है कि यदि आप performBatchUpdatesएक यूआईवीवाई एनीमेशन ब्लॉक में लपेटते हैं , तो डिफ़ॉल्ट एनीमेशन के बजाय यूआईवीईवाई एनीमेशन का उपयोग किया जाता है, इसलिए आप एनीमेशन अवधि को 0 पर सेट कर सकते हैं, जैसे:

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

यदि आप आवेषण और हटाए जाने के दौरान iOS 7 बसंत एनिमेशन का उपयोग करना चाहते हैं तो यह अतिरिक्त शांत है!


1
धन्यवाद। यह स्टॉपवॉच टाइमर को uicollectionview कोशिकाओं को जोड़ने में बहुत मददगार था।
हैटाइक

प्रतिभाशाली! मैंने यह सम्मिलित करने के साथ प्रयोग किया, और कीबोर्ड के साथ, सेल को सम्मिलित किए जाने के बाद संग्रह दृश्य को एक नई ऑफसेट पर चेतन करने के लिए।
डेविड एच

5
जैसा कि पीटर कहते हैं, यह अन्य एनिमेशन के साथ हस्तक्षेप करता है। इसके बजाय, आपको पूर्ण ब्लॉक के बाहर [UIView setAnimationsEnabled: YES] को कॉल करना चाहिए। इस तरह आप केवल उस 1 एनीमेशन को रोकते हैं।
अडलई हॉलर

2
मैंने एक वैकल्पिक तरीका जोड़ा, जो बिल्कुल यही काम करता है।
सैम

1
performBatchUpdatesअंदर लपेटना animateWithDurationशानदार है! पारितोषिक के लिए धन्यवाद!
रॉबर्ट

19

पुन: लोड करने के बाद UICollectionView चेतन आइटम। aAndIndexPaths (फीका एनीमेशन) कहा जाता है।

क्या इस एनीमेशन से बचने का कोई तरीका है?

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 पर काम कर रहा था और एक ही सवाल था, इसलिए यह यहाँ किसी के लिए भी है जो एक ही समस्या के साथ आता है।


1
"वाह यह वास्तव में अच्छी तरह से काम करता है" के प्रभाव के जवाब पर 3 या 4 टिप्पणियां थीं! किसी ने टिप्पणियों को हटाने का फैसला किया। मुझे लगता है, तथ्यात्मक रूप से, यह इसे पूरा करने का आधुनिक और गैर-हैक करने वाला तरीका है, और वे टिप्पणियां इस बात की मान्यता थीं।
मैट मैक

8

मैंने ऐसा करने के लिए UICollectionView पर एक श्रेणी लिखी । पुनः लोड करते समय चाल सभी एनिमेशन को निष्क्रिय करना है:

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

[self reloadItemsAtIndexPaths:indexPaths];

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

मुझे Apple से भी जवाब मिला कि यह कोई एनीमेशन नहीं करना चाहिए, अगर यह एक बग है। मुझे नहीं पता कि मैं कुछ गलत कर रहा हूं या यह बग है।
मार्सिन

2
आप इसके लिए सिर्फ CATransaction.setDisableActions(true)आशुलिपि के रूप में भी कर सकते हैं ।
Cifilter

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

यह स्विफ्ट 3 वाक्य रचना है
अमजद तुबासी

यह अच्छा काम किया, यहां तक ​​कि UIView.performWithoutAnimation की तुलना में बेहतर
लांस सामरिया

5

यहाँ performBatchUpdatesएनीमेशन के बिना एक स्विफ्ट 3 संस्करण है a UICollectionView। मुझे यह मेरे लिए बेहतर काम करने के लिए मिला collectionView.reloadData()क्योंकि रिकॉर्ड्स डालने पर यह सेल स्वैपिंग को कम करता है।

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

        })
    }
}

2
- (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];
    }

}

1

बस अपने $ 0.02 को जोड़ने के लिए, मैंने चयनित उत्तर के दोनों संस्करणों की कोशिश की, और मूल तरीके से मेरे उद्देश्यों के लिए बेहतर काम किया। मैं एक अनंत स्क्रॉल कैलेंडर दृश्य पर काम कर रहा हूं जो किसी उपयोगकर्ता को दिए गए सप्ताह में कैलेंडर में प्रवेश करने की अनुमति देता है और फिर आगे और पीछे स्वाइप करके किसी सूची को फ़िल्टर करने के लिए व्यक्तिगत दिनों का चयन करता है।

मेरे कार्यान्वयन में, पुराने उपकरणों पर प्रदर्शन करने वाली चीजों को रखने के लिए, कैलेंडर दृश्य का प्रतिनिधित्व करने वाली तिथियों की सरणी को अपेक्षाकृत छोटा रखा जाना चाहिए, जिसका अर्थ है 3 सप्ताह के मध्य में उपयोगकर्ता के साथ, लगभग 5 सप्ताह की तारीखें। दूसरे दृष्टिकोण का उपयोग करने के साथ समस्या है, एक दूसरा चरण है जहां आपको संग्रह दृश्य को बिना एनीमेशन के बीच में वापस स्क्रॉल करना होगा, जो अवरुद्ध आधार एनीमेशन के साथ किसी कारण से बहुत दांतेदार उपस्थिति के लिए बनाता है।

मेरा कोड:

[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];

0
 func reloadRowsWithoutAnimation(at indexPaths: [IndexPath]) {
        let contentOffset = collectionView.contentOffset
        UIView.setAnimationsEnabled(false)
        collectionView.performBatchUpdates {
            collectionView.reloadItems(at: indexPaths)
        }
        UIView.setAnimationsEnabled(true)
        collectionView.setContentOffset(contentOffset, animated: false)
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.