重新加载部分而不重新加载部分标题

我有一个UITableView ,标题视图中有一个UISegmentedControl 。 它应该与App Store应用程序完全相同:当用户滚动时,标题中的标题会滚动屏幕,但segmentedControl粘在navigationBar

屏幕

当用户选择一个段时,标题下面的部分应该重新加载一个漂亮的UITableViewRowAnimation 。 但是,当我调用tableView:reloadSections:withRowAnimation: ,标题视图也是动画的,我想阻止它,因为它看起来很糟糕。

这是我的代码:

 - (void)selectedSegmentIndexChanged:(UISegmentedControl *)sender { int index = sender.selectedSegmentIndex; if (index  self.oldIndex) { [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationRight]; } self.oldIndex = index; } 

任何人都知道如何重新加载标题下方的部分而不重新加载标题本身?

也许你应该试试

 [self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationLeft] //or UITableViewRowAnimationRight 

但是,我不确定,但我认为在你重新加载的行比以前少的情况下会出现一些错误。


编辑

我认为你可以处理[tableView beginUpdates][tableView endUpdates]来解决你的问题。

例如,您要显示2个数据arrays。 我们将它们命名为oldArraynewArray 。 你可以做什么的样本:

 - (void)selectedSegmentIndexChanged:(UISegmentedControl *)sender { [self.tableView setDataSource: newArray]; int nbRowToDelete = [oldArray count]; int nbRowToInsert = [newArray count]; NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init]; for (NSInteger i = 0; i < nbRowToInsert; i++) { [indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:section]]; } NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init]; for (NSInteger i = 0; i < nbRowToDelete; i++) { [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:section]]; } [self.tableView beginUpdates]; [self.tableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationLeft]; [self.tableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationRight]; [self.tableView endUpdates]; } 

如果您使用的是Swift 2.0 ,请随意使用此扩展程序。

请注意 :传入错误的oldCountnewCount会使程序崩溃。

 extension UITableView{ func reloadRowsInSection(section: Int, oldCount:Int, newCount: Int){ let maxCount = max(oldCount, newCount) let minCount = min(oldCount, newCount) var changed = [NSIndexPath]() for i in minCount.. oldCount){ insertRowsAtIndexPaths(changed, withRowAnimation: .Fade) }else if(oldCount > newCount){ deleteRowsAtIndexPaths(changed, withRowAnimation: .Fade) } if(newCount > oldCount || newCount == oldCount){ reloadRowsAtIndexPaths(reload, withRowAnimation: .None) } endUpdates() } 

尝试这个:

 BOOL needsReloadHeader = YES; UIView *oldHeaderView = nil; -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIView *headerToReturn = nil; if(needsReloadHeader == YES) { headerToReturn = [[UIView alloc] init]; // ... // custom your header view in this block // and save // ... oldHeaderView = headerToReturn; } else { headerToReturn = oldHeaderView; } return headerToReturn; } 

你只需要在其他地方将’needsReloadHeader’改为’NO’。

简单的答案就是不要重新加载动画部分,只需使用UITableViewRowAnimationNone即可。

现在你正在使用UITableViewRowAnimationLeft和UITableViewRowAnimationRight,它也会滑入你的部分。

但是,即使使用UITableViewRowAnimationNone,如果更新前的单元格数与更新后的单元格数不同,则仍会为行设置动画。

此外, 这里有关于这个主题的精彩阅读。

干杯。

Intentss扩展的Objective-c版本

 @interface UITableView (Extensions) - (void)reloadRowsInSection:(NSUInteger)sectionIndex withRowAnimation:(UITableViewRowAnimation)rowAnimation oldCount:(NSUInteger)oldCount newCount:(NSUInteger)newCount; @end @implementation UITableView (Extensions) - (void)reloadRowsInSection:(NSUInteger)sectionIndex withRowAnimation:(UITableViewRowAnimation)rowAnimation oldCount:(NSUInteger)oldCount newCount:(NSUInteger)newCount { NSUInteger minCount = MIN(oldCount, newCount); NSMutableArray *insert = [NSMutableArray array]; NSMutableArray *delete = [NSMutableArray array]; NSMutableArray *reload = [NSMutableArray array]; for (NSUInteger row = oldCount; row < newCount; row++) { [insert addObject:[NSIndexPath indexPathForRow:row inSection:sectionIndex]]; } for (NSUInteger row = newCount; row < oldCount; row++) { [delete addObject:[NSIndexPath indexPathForRow:row inSection:sectionIndex]]; } for (NSUInteger row = 0; row < minCount; row++) { [reload addObject:[NSIndexPath indexPathForRow:row inSection:sectionIndex]]; } [self beginUpdates]; [self insertRowsAtIndexPaths:insert withRowAnimation:rowAnimation]; [self deleteRowsAtIndexPaths:delete withRowAnimation:rowAnimation]; [self reloadRowsAtIndexPaths:reload withRowAnimation:rowAnimation]; [self endUpdates]; } @end 

您正在重新加载该部分,因此该部分中的所有内容都将被重新加载(包括标题)。

为什么不把UISegmentedControl放在UITableView的tableHeaderView呢? 这将准确地说明你所追求的行为。

这是您可以使用并仍然使用动画的另一种方式。

假设您有一个动态DataSource,当您选择某些内容时会更改,并且您只想更新该部分的行,同时保持部分标题位于顶部,不受影响。

 /** I get the desired handler from the handler collection. This handler is just a simple NSObject subclass subscribed to UITableViewDelegate and UITableViewDataSource protocols. **/ id handler = [self.tableViewHandlers objectForKey:[NSNumber numberWithInteger:index]]; /** Get the rows which will be deleted */ NSInteger numberOfRows = [self.tableView numberOfRowsInSection:sectionIndex]; NSMutableArray* indexPathArray = [NSMutableArray array]; for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++){ [indexPathArray addObject:[NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex]]; } /** Update the handler */ [self.tableView setDataSource:handler]; [self.tableView setDelegate:handler]; /** Get the rows which will be added */ NSInteger newNumberOfRows = [handler tableView:self.tableView numberOfRowsInSection:sectionIndex]; NSMutableArray* newIndexPathArray = [NSMutableArray array]; for (int rowIndex = 0; rowIndex < newNumberOfRows; rowIndex++){ [newIndexPathArray addObject:[NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex]]; } /** Perform updates */ [self.tableView beginUpdates]; [self.tableView deleteRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationFade]; [self.tableView insertRowsAtIndexPaths:newIndexPathArray withRowAnimation:UITableViewRowAnimationFade]; [self.tableView endUpdates]; 

作为注释,请坚持指定的操作顺序,UITableView要求它。 如果您只有一个处理程序(数据源和委托),则可以轻松修改上述代码以获得相同的结果。