UICollectionView ทำให้รายการเคลื่อนไหวหลังจากรีโหลดItemsAtIndexPathsเรียกว่า (ภาพเคลื่อนไหวจาง)
มีวิธีหลีกเลี่ยงภาพเคลื่อนไหวนี้หรือไม่?
iOS 6
UICollectionView ทำให้รายการเคลื่อนไหวหลังจากรีโหลดItemsAtIndexPathsเรียกว่า (ภาพเคลื่อนไหวจาง)
มีวิธีหลีกเลี่ยงภาพเคลื่อนไหวนี้หรือไม่?
iOS 6
คำตอบ:
เป็นที่น่าสังเกตว่าหากคุณกำหนดเป้าหมายเป็น iOS 7 ขึ้นไปคุณสามารถใช้UIView
วิธีการใหม่นี้performWithoutAnimation:
ได้ ฉันสงสัยว่าภายใต้ประทุนนี้ทำเช่นเดียวกับคำตอบอื่น ๆ ที่นี่ (ปิดใช้งานUIView
แอนิเมชั่นชั่วคราว/ แอ็คชั่น Core Animation) แต่ไวยากรณ์นั้นดีและสะอาด
ดังนั้นสำหรับคำถามนี้โดยเฉพาะ ...
วัตถุประสงค์ -C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
รวดเร็ว:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
แน่นอนหลักการนี้สามารถใช้ได้กับทุกสถานการณ์ที่คุณต้องการเพื่อให้แน่ใจว่าการเปลี่ยนแปลงจะไม่เคลื่อนไหว
คุณสามารถลองสิ่งนี้:
UICollectionView *collectionView;
...
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
ฉันยังพบว่าหากคุณรวมperformBatchUpdates
บล็อกแอนิเมชั่น UIView แอนิเมชั่น UIView จะถูกใช้แทนภาพเคลื่อนไหวเริ่มต้นดังนั้นคุณสามารถตั้งค่าระยะเวลาการเคลื่อนไหวเป็น 0 ได้ดังนี้
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
นี่เป็นสิ่งที่ยอดเยี่ยมมากหากคุณต้องการใช้แอนิเมชั่นสปริงของ iOS 7 ระหว่างการแทรกและลบ!
performBatchUpdates
ข้างในanimateWithDuration
ก็แจ่ม! ขอบคุณสำหรับทิป!
UICollectionView ทำให้รายการเคลื่อนไหวหลังจากรีโหลดItemsAtIndexPathsเรียกว่า (ภาพเคลื่อนไหวจาง)
มีวิธีหลีกเลี่ยงภาพเคลื่อนไหวนี้หรือไม่?
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];
}
CATransaction.setDisableActions(true)
จดชวเลขได้เช่นกัน
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
นี่คือเวอร์ชัน Swift 3 ที่performBatchUpdates
ไม่มีภาพเคลื่อนไหวเป็น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
})
}
}
- (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];
}
}
เพียงแค่เพิ่ม 0.02 ดอลลาร์ของฉันฉันได้ลองใช้คำตอบที่เลือกทั้งสองเวอร์ชันและวิธีเดิมใช้ได้ดีกว่าสำหรับวัตถุประสงค์ของฉัน ฉันกำลังทำงานกับมุมมองปฏิทินแบบเลื่อนไม่สิ้นสุดซึ่งอนุญาตให้ผู้ใช้เข้าสู่ปฏิทินในสัปดาห์ที่กำหนดจากนั้นปัดไปมาและเลือกวันละรายการเพื่อกรองรายการ
ในการใช้งานของฉันเพื่อให้สิ่งต่างๆมีประสิทธิภาพบนอุปกรณ์รุ่นเก่าอาร์เรย์ของวันที่ที่แสดงถึงมุมมองปฏิทินจะต้องมีขนาดค่อนข้างเล็กซึ่งหมายถึงการถือวันที่ประมาณ 5 สัปดาห์โดยที่ผู้ใช้อยู่ตรงกลางในสัปดาห์ที่ 3 ปัญหาในการใช้แนวทางที่สองคือมีขั้นตอนที่สองที่คุณต้องเลื่อนมุมมองคอลเลกชันกลับไปตรงกลางโดยไม่มีภาพเคลื่อนไหวซึ่งทำให้มีลักษณะขรุขระมากด้วยเหตุผลบางประการกับภาพเคลื่อนไหวพื้นฐานที่ถูกบล็อก
รหัสของฉัน:
[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];
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)
}