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

时间:2013-12-27 14:47:11

标签: ios objective-c uitableview

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

screen

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

这是我的代码:

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

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

7 个答案:

答案 0 :(得分:24)

也许你应该试试

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

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


修改

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

例如,您要显示2个数据阵列。我们将其命名为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];
}

答案 1 :(得分:4)

如果您使用的是 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..<maxCount {
        let indexPath = NSIndexPath(forRow: i, inSection: section)
        changed.append(indexPath)
    }

    var reload = [NSIndexPath]()
    for i in 0..<minCount{
        let indexPath = NSIndexPath(forRow: i, inSection: section)
        reload.append(indexPath)
    }

    beginUpdates()
    if(newCount > oldCount){
        insertRowsAtIndexPaths(changed, withRowAnimation: .Fade)
    }else if(oldCount > newCount){
        deleteRowsAtIndexPaths(changed, withRowAnimation: .Fade)
    }
    if(newCount > oldCount || newCount == oldCount){
        reloadRowsAtIndexPaths(reload, withRowAnimation: .None)
    }
    endUpdates()

}

答案 2 :(得分:3)

试试这个:

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'。

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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

为什么不将UISegmentedControl放在UITableView的tableHeaderView中呢?这样就可以完全实现你所追求的行为。

答案 5 :(得分:0)

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

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

但是,即使使用UITableViewRowAnimationNone,如果更新前的单元格数与更新后的单元格数不同,行仍将显示动画。

另外,关于这个主题的很好的阅读,here

干杯。

答案 6 :(得分:0)

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

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

/** 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要求它。 如果您只有一个处理程序(数据源和委托),则可以轻松修改上述代码以获得相同的结果。