बदलते समय एक UITableView चेतन के लिए पुनः लोड करें


183

मेरे पास एक UITableView है जिसमें दो मोड हैं। जब हम मोड के बीच स्विच करते हैं तो मेरे पास प्रति अनुभाग और अनुभागों की एक अलग संख्या होती है। आदर्श रूप से, यह कुछ अच्छा एनीमेशन करेगा जब तालिका बढ़ती है या सिकुड़ती है।

यहाँ कोड मैंने कोशिश की है, लेकिन यह कुछ भी नहीं करता है:

CGContextRef context = UIGraphicsGetCurrentContext(); 
[UIView beginAnimations:nil context:context]; 
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
[UIView setAnimationDuration:0.5]; 

[self.tableView reloadData];
[UIView commitAnimations];

कैसे मैं यह कर सकता है पर कोई विचार?

जवाबों:


400

वास्तव में, यह बहुत आसान है:

[_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];

से प्रलेखन :

इस पद्धति को कॉल करने से तालिका दृश्य निर्दिष्ट वर्गों के लिए नई कोशिकाओं के लिए अपने डेटा स्रोत का कारण बनता है। तालिका दृश्य नई कोशिकाओं के सम्मिलन को एनिमेट करता है क्योंकि यह पुरानी कोशिकाओं को बाहर निकालता है।


13
और बस इस पृष्ठ पर सबसे अच्छा जवाब!
मथायस डी

40
यह पूरी तरह से सही नहीं है, क्योंकि यह केवल पहले खंड को फिर से लोड करेगा। यदि आपकी टेबल में कई सेक्शन हैं, तो यह काम नहीं करेगा
Nosrettap

4
यह संभव है कि अगर कोई डेटा नहीं बदला है तो आपको एक अपवाद मिलेगा। मेरा जवाब
Matej

8
@Nosrettap: यदि आप अपने टेबल व्यू लोड के अधिक या सभी अनुभागों को प्राप्त करना चाहते हैं, तो आपको बस इतना करना है कि अपने NSIndexSet को सभी अनुभाग अनुक्रमितों के साथ विस्तारित करें, जो कि ताज़ा करने की आवश्यकता है
JonE

स्विफ्ट संस्करण: _tableView.reloadSections(NSIndexSet(index: 0), withRowAnimation: .Fade)विशेष रूप से, हालांकि, यह केवल धारा 0 को अद्यतन करता है, जो कि डिफ़ॉल्ट, पहला खंड है।
kbpontius

262

आप उपयोग करना चाहते हैं:

उद्देश्य सी

[UIView transitionWithView: self.tableView
                  duration: 0.35f
                   options: UIViewAnimationOptionTransitionCrossDissolve
                animations: ^(void)
 {
      [self.tableView reloadData];
 }
                completion: nil];

तीव्र

UIView.transitionWithView(tableView,
                          duration: 0.35,
                          options: .TransitionCrossDissolve,
                          animations:
{ () -> Void in
    self.tableView.reloadData()
},
                          completion: nil);

स्विफ्ट 3, 4 और 5

UIView.transition(with: tableView,
                  duration: 0.35,
                  options: .transitionCrossDissolve,
                  animations: { self.tableView.reloadData() }) // left out the unnecessary syntax in the completion block and the optional completion parameter

कोई झंझट नहीं। : डी

आप UIViewAnimationOptionTransitionsकूलर के प्रभावों के लिए अपनी इच्छानुसार कोई भी उपयोग कर सकते हैं :

  • transitionNone
  • transitionFlipFromLeft
  • transitionFlipFromRight
  • transitionCurlUp
  • transitionCurlDown
  • transitionCrossDissolve
  • transitionFlipFromTop
  • transitionFlipFromBottom

2
यह उपयोगी है अगर आपके टेबलव्यू की शुरुआत / समाप्ति स्थिति बहुत अलग होगी (और यह जोड़ने या हटाने के लिए वर्गों और पंक्तियों की गणना करने के लिए जटिल होगी), लेकिन आप कुछ कम भटकते हैं कि गैर-एनिमेटेड रीलोड।
बेन पैकर्ड

1
यह विधियों में निर्मित है, इसका उपयोग करते हुए टेबलव्यू को फिर से लोड करने के रूप में अच्छा एनीमेशन नहीं है, लेकिन यहां उल्लिखित उच्च रेटेड पद्धति के विपरीत, यह तब काम करता है जब आपके पास कई खंड होते हैं।
मार्क ब्रिजेस

1
बाकी सब कोशिश करने के बाद वाह यह मेरे लिए बिल्कुल सही है
लुकास गूसेन

1
@MarkBridges उच्च श्रेणी के उत्तर कई वर्गों के साथ काम करता है :) -[_tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)] withRowAnimation:UITableViewRowAnimationFade];
lobianco

2
@ एंथनी यह काम नहीं करता है यदि अंतिम स्थिति में प्रारंभिक राज्य की तुलना में अधिक / कम अनुभाग हैं। फिर आपको मैन्युअल रूप से ट्रैक करना होगा कि कौन से अनुभाग जोड़े गए / हटाए गए, जो काफी परेशानी वाला है।
निकोलोवस्की

78

CATransitionवर्ग का उपयोग करने की अधिक स्वतंत्रता है ।

यह लुप्त होती तक ही सीमित नहीं है, लेकिन आंदोलनों को भी कर सकता है।


उदाहरण के लिए:

(आयात करना न भूलें QuartzCore)

CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.fillMode = kCAFillModeForwards;
transition.duration = 0.5;
transition.subtype = kCATransitionFromBottom;

[[self.tableView layer] addAnimation:transition forKey:@"UITableViewReloadDataAnimationKey"];

typeअपनी आवश्यकताओं से मेल खाने के लिए बदलें , जैसे kCATransitionFadeआदि।

स्विफ्ट में कार्यान्वयन:

let transition = CATransition()
transition.type = kCATransitionPush
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.fillMode = kCAFillModeForwards
transition.duration = 0.5
transition.subtype = kCATransitionFromTop
self.tableView.layer.addAnimation(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()

कैरमेन्सिशन का संदर्भ

स्विफ्ट 5:

let transition = CATransition()
transition.type = CATransitionType.push
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.fillMode = CAMediaTimingFillMode.forwards
transition.duration = 0.5
transition.subtype = CATransitionSubtype.fromTop
self.tableView.layer.add(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()

यह एकल पंक्तियों / अनुभागों के बजाय तालिका को संपूर्ण रूप से एनिमेट करता है।
अगोस

@Agos यह अभी भी सवाल का जवाब देता है। एक प्रश्न "केवल एक पंक्ति को कैसे फिर से लोड करें" में एक अलग जवाब है, जैसे कि एनीमेशन को layerसंपत्ति के लिए लागू करना UITableViewCell
मतज

@matejkramny मुझे उम्मीद थी कि तालिका अलग-अलग पंक्तियों को (जैसे प्रश्न में संदर्भित) चेतन करेगी, लेकिन यह विधि एक ही बार में सभी तालिका को धक्का देती है। हो सकता है कि मुझसे कुछ छूट रहा हो?
Agos

@AOS हम्म नहीं यह करने वाला है। यह केवल आधा टेबल नहीं कर सकता क्योंकि क्वार्ट्जकोर सीधे दृश्य को संशोधित करता है। आप तालिका दृश्य से कोशिकाओं को प्राप्त करने का प्रयास कर सकते हैं, और फिर इस एनीमेशन को प्रत्येक पर लागू कर सकते हैं (लेकिन यह सुनिश्चित नहीं होगा कि यह काम करेगा)
Matej

2
kCATransitionFade धन्यवाद के साथ एक आकर्षण की तरह काम किया! :)
क्लेयरेज़

60

मेरा मानना ​​है कि आप अपनी डेटा संरचना को अपडेट कर सकते हैं, फिर:

[tableView beginUpdates];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView endUpdates];

इसके अलावा, "withRowAnimation" एक बूलियन नहीं है, लेकिन एक एनीमेशन शैली है:

UITableViewRowAnimationFade,
UITableViewRowAnimationRight,
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,
UITableViewRowAnimationMiddle

सरल सामान, लेकिन स्टैकऑवरफ्लो से सीधे जाने के लिए और ट्रावल डॉक्स की तुलना में आपको जिस स्निपेट की आवश्यकता है उसे प्राप्त करना आसान है। । धन्यवाद!
जैस्पर ब्लूज

24

ये सभी उत्तर यह मानते हैं कि आप केवल 1 सेक्शन के साथ यूआईटेबल व्यू का उपयोग कर रहे हैं।

उन स्थितियों को सही ढंग से संभालने के लिए जहां आपके पास 1 से अधिक अनुभाग उपयोग हैं:

NSRange range = NSMakeRange(0, myTableView.numberOfSections);
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
[myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];

(नोट: आपको यह सुनिश्चित करना चाहिए कि आपके पास 0 से अधिक अनुभाग हैं!)

ध्यान देने वाली एक और बात यह है कि यदि आप एक साथ इस कोड के साथ अपने डेटा स्रोत को अपडेट करने का प्रयास करते हैं तो आप NSInternalInconsistencyException में चल सकते हैं। यदि यह मामला है, तो आप इसके समान तर्क का उपयोग कर सकते हैं:

int sectionNumber = 0; //Note that your section may be different

int nextIndex = [currentItems count]; //starting index of newly added items

[myTableView beginUpdates];

for (NSObject *item in itemsToAdd) {
    //Add the item to the data source
    [currentItems addObject:item];

    //Add the item to the table view
    NSIndexPath *path = [NSIndexPath indexPathForRow:nextIndex++ inSection:sectionNumber];
    [myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationAutomatic];
}

[myTableView endUpdates];

3
खंड गणना के बारे में अच्छी बात है, लेकिन मेरे पास केवल एक खंड था और आपके कोड में एक-एक त्रुटि थी। मुझे आपके कोड की पहली पंक्ति को NSRange रेंज = NSMakeRange (0, myTableView.numberOfSections) में बदलना पड़ा;
डेनियल आयटेकिन

18

दृष्टिकोण का तरीका यह है कि टेबल व्यू को पंक्तियों और वर्गों को हटाने और जोड़ने के लिए कहा जाए

insertRowsAtIndexPaths:withRowAnimation:,
deleteRowsAtIndexPaths:withRowAnimation:,
insertSections:withRowAnimation:और
deleteSections:withRowAnimation:

UITableView के तरीके।

जब आप इन विधियों को कॉल करते हैं, तो तालिका आपके द्वारा अनुरोधित वस्तुओं को अंदर / बाहर चेतन करेगी, फिर स्वयं पर पुनः लोड करें कॉल करें ताकि आप इस एनीमेशन के बाद राज्य को अपडेट कर सकें। यह हिस्सा महत्वपूर्ण है - यदि आप सब कुछ दूर कर देते हैं, लेकिन तालिका के डेटा स्रोत द्वारा लौटाए गए डेटा को नहीं बदलते हैं, तो एनीमेशन पूरा होने के बाद पंक्तियाँ फिर से दिखाई देंगी।

तो, आपका आवेदन प्रवाह होगा:

[self setTableIsInSecondState:YES];

[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];

जब तक आपकी तालिका के डेटा स्रोत विधियाँ जाँच [self tableIsInSecondState](या जो भी) करके वर्गों और पंक्तियों के नए सेट को सही लौटाती हैं, यह आपके द्वारा खोजे जा रहे प्रभाव को प्राप्त कर लेगा।


16

मैं शीर्ष उत्तर पर टिप्पणी नहीं कर सकता, लेकिन एक त्वरित कार्यान्वयन होगा:

self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade)

आप उतने अनुभागों को शामिल कर सकते हैं जितना आप पुनः लोड करने के लिए पहले तर्क में अपडेट करना चाहते हैं।

डॉक्स से उपलब्ध अन्य एनिमेशन: https://developer.apple.com/reference/uikit/uitableviewrowanimation

फीका सम्मिलित या हटाई गई पंक्ति या पंक्तियाँ तालिका दृश्य में या उसके बाहर फीकी हो जाती हैं।

सही सम्मिलित पंक्ति या पंक्तियाँ दाईं ओर से स्लाइड करती हैं; हटा दी गई पंक्ति या पंक्तियाँ दाईं ओर खिसक जाती हैं।

बाएँ सम्मिलित पंक्ति या पंक्तियाँ बाईं ओर से स्लाइड करती हैं; हटाई गई पंक्ति या पंक्तियाँ बाईं ओर स्लाइड करती हैं।

शीर्ष सम्मिलित पंक्ति या पंक्तियाँ ऊपर से स्लाइड करती हैं; हटाई गई पंक्ति या पंक्तियाँ ऊपर की ओर स्लाइड करती हैं।

नीचे सम्मिलित पंक्ति या पंक्तियाँ नीचे से स्लाइड करती हैं; हटाई गई पंक्ति या पंक्तियाँ नीचे की ओर स्लाइड करती हैं।

स्थिति कोई भी सम्मिलित या हटाई गई पंक्तियाँ डिफ़ॉल्ट एनिमेशन का उपयोग नहीं करती हैं।

मध्य तालिका का दृश्य उन पुरानी और नई कोशिकाओं को रखने का प्रयास करता है जो उनके द्वारा की गई जगह पर केन्द्रित होती हैं। आईफोन 3.2 में उपलब्ध है।

स्वचालित तालिका दृश्य आपके लिए एक उपयुक्त एनीमेशन शैली चुनता है। (IOS 5.0 में पेश किया गया है।)


1
स्विफ्ट 4.2 के लिए: self.tableView.reloadSections ([0], साथ: UITableView.RowAnimation.fade)
19 को रीफॉस्टिंग

14

@ वर्जन उत्तर के लिए स्विफ्ट 4 संस्करण:

tableView.reloadSections(IndexSet(integer: 0), with: .automatic)

9

स्विफ्ट कार्यान्वयन:

let range = NSMakeRange(0, self.tableView!.numberOfSections())
let indexSet = NSIndexSet(indexesInRange: range)
self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)


1

मेरे मामले में, मैं टेबलव्यू में 10 और पंक्तियों को जोड़ना चाहता था (कार्यक्षमता के "अधिक परिणाम दिखाने के लिए") और मैंने इसे बनाया:

  NSInteger tempNumber = self.numberOfRows;
  self.numberOfRows += 10;
  NSMutableArray *arrayOfIndexPaths = [[NSMutableArray alloc] init];
  for (NSInteger i = tempNumber; i < self.numberOfRows; i++) {
    [arrayOfIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
  }
  [self.tableView beginUpdates];
  [self.tableView insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation:UITableViewRowAnimationTop];
  [self.tableView endUpdates];

ज्यादातर मामलों में, "self.numberOfRows" के बजाय, आप आमतौर पर टेबलव्यू के लिए ऑब्जेक्ट की सरणी की गिनती का उपयोग करेंगे। तो यह सुनिश्चित करने के लिए कि यह समाधान आपके लिए अच्छी तरह से काम करता है, "arrayOfIndexPaths" को सम्मिलित किए जा रहे पंक्तियों के सूचकांक पथ का एक सटीक सरणी होना चाहिए। यदि इस इंडेक्स पथ में से किसी के लिए पंक्ति मौजूद है, तो कोड क्रैश हो सकता है, इसलिए आपको "इंडलोड रोस्टैक्सथैक्स: withRowAnimation:" विधि का उपयोग करना चाहिए ताकि क्रैश से बचने के लिए उन इंडेक्स पथों के लिए


1

यदि आप UITableView कोशिकाओं में अपने स्वयं के कस्टम एनिमेशन जोड़ना चाहते हैं, तो उपयोग करें

[theTableView reloadData];
[theTableView layoutSubviews];
NSArray* visibleViews = [theTableView visibleCells];

दृश्यमान कोशिकाओं की एक सरणी प्राप्त करने के लिए। फिर प्रत्येक सेल में कोई कस्टम एनीमेशन जोड़ें।

एक चिकनी कस्टम सेल एनीमेशन के लिए पोस्ट किए गए इस जिस्ट को देखें। https://gist.github.com/floprr/1b7a58e4a18449d962bd


1

स्विफ्ट में पुनः लोड किए बिना () स्विफ्ट को इस तरह किया जा सकता है (संस्करण 2.2 के अनुसार):

tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove ?? 0

// Do your work here
while numOfCellsToRemove > 0 {
    // ...or here, if you need to add/remove the same amount of objects to/from somewhere
    indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
    numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()

यदि एनीमेशन समाप्त होने के बाद आपको पुनः लोड () कॉल करने की आवश्यकता है, तो आप इस तरह कैटरेन्सेशन में परिवर्तन को गले लगा सकते हैं:

CATransaction.begin()
CATransaction.setCompletionBlock({() in self.tableview.reloadData() })
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove.count ?? 0

// Do your work here
while numOfCellsToRemove > 0 {
     // ...or here, if you need to add/remove the same amount of objects to/from somewhere
     indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
     numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
CATransaction.commit()

जब आप पंक्तियों को हटाते हैं तो तर्क को दिखाया जाता है, लेकिन पंक्तियों को जोड़ने के लिए भी यही विचार काम करता है। आप एनिमेशन को UITableViewRowAnimation.Left में बदल सकते हैं। इसे साफ-सुथरा बनाने के लिए, या अन्य उपलब्ध एनिमेशनों की सूची में से चुन सकते हैं।


1
CATransition *animation = [CATransition animation];
animation.duration = .3;
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setDuration:.3];

[[_elementTableView layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"];

[tableView reloadData];

2
अवधि .3दो बार क्यों निर्धारित करें ?
पिंग

1

सभी वर्गों को पुनः लोड करने के लिए , केवल कस्टम अवधि के साथ एक नहीं ।

कस्टम अवधि सेट करने durationके UIView.animateलिए उपयोगकर्ता पैरामीटर ।

UIView.animate(withDuration: 0.4, animations: { [weak self] in
    guard let `self` = self else { return }
    let indexSet = IndexSet(integersIn: 0..<self.tableView.numberOfSections)
    self.tableView.reloadSections(indexSet, with: UITableView.RowAnimation.fade)
})

0

UITableViewस्विफ्ट में देशी एनिमेशन

एक साथ सभी पंक्तियों को सम्मिलित करें और हटाएं tableView.performBatchUpdatesताकि वे एक साथ हो सकें। @IKenndac के उत्तर पर बिल्डिंग जैसे तरीकों का उपयोग करें:

  • tableView.insertSections
  • tableView.insertRows
  • tableView.deleteSections
  • tableView.deleteRows

उदाहरण के लिए:

 tableView.performBatchUpdates({
   tableView.insertSections([0], with: .top)
 })

यह शीर्ष पर लोड होने वाले एनीमेशन के साथ शून्य स्थिति पर एक अनुभाग सम्मिलित करता है। इसे फिर से चलाया जाएगाcellForRowAt विधि और उस स्थिति में एक नए सेल के लिए जाँच करेगा। आप विशिष्ट एनिमेशन के साथ इस तरह से पूरी तालिका दृश्य पुनः लोड कर सकते हैं।

पुन: ओपी प्रश्न, वैकल्पिक तालिका दृश्य स्थिति के लिए कोशिकाओं को दिखाने के लिए एक सशर्त ध्वज की आवश्यकता होगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.