添加新数据时,Tableview 会滚动到顶部。无限滚动

Posted

技术标签:

【中文标题】添加新数据时,Tableview 会滚动到顶部。无限滚动【英文标题】:Tableview scrolls to top when adding new data. Infinite scroll 【发布时间】:2016-12-17 04:27:10 【问题描述】:

当我滚动到表格视图的底部并使用下一个偏移量获取更多数据时,我会将新对象添加到我的数据数组中。然而,我的 tableview 重新加载并返回到第一个单元格。我正在努力防止这种情况发生。

- (void)fetchMovies 
    [MBProgressHUD showHUDAddedTo:self.view animated:YES];

    [self.networkingHelper fetchNowPlayingWithCompletionHandler:^(NSArray *objects, NSError *error) 

     if (error) 
         [self showErrorView:self.errorView];
      else 
         [self hideErrorView:self.errorView];
     

     [self.movies addObjectsFromArray:objects];
     self.displayedItems = self.movies;

     dispatch_async(dispatch_get_main_queue(), ^
         self.isMoreDataLoading = false;

         if ([[NSThread currentThread] isMainThread])
             NSLog(@"In main thread--completion handler");

             [self.refreshControl endRefreshing];
             [self.loadingMoreView stopAnimating];
             [MBProgressHUD hideHUDForView:self.view animated:YES];
          else 
             NSLog(@"Not in main thread--completion handler");
         
         );
       

     ];

编辑尝试添加此

- (void)fetchMovies 
    [MBProgressHUD showHUDAddedTo:self.view animated:YES];

    [self.networkingHelper fetchNowPlayingWithCompletionHandler:^(NSArray *objects, NSError *error)
     

         if (error)
         
             [self showErrorView:self.errorView];
         
         else
         
             [self hideErrorView:self.errorView];

         
         [self.movies addObjectsFromArray:objects];
         self.displayedItems = self.movies;


         dispatch_async(dispatch_get_main_queue(), ^
             self.isMoreDataLoading = false;


             if ([[NSThread currentThread] isMainThread])
                 NSLog(@"In main thread--completion handler");

                 CGFloat oldOffset = self.moviesTableView.contentSize.height;
                 [self.moviesTableView reloadData];
                 CGFloat onewOffset = self.moviesTableView.contentSize.height;
                 CGPoint new = CGPointMake(0, onewOffset - oldOffset);

                 [self.moviesTableView setContentOffset:new];

                 [self.refreshControl endRefreshing];
                 [self.loadingMoreView stopAnimating];
                 [MBProgressHUD hideHUDForView:self.view animated:YES];


             
             else
                 NSLog(@"Not in main thread--completion handler");
             

             );
     

     ];

仍然滚动到顶部

【问题讨论】:

我想我不是很清楚。我的意思是我的表格视图会自动自动转到顶部单元格。我试图阻止这种情况。因此用户可以继续滚动浏览下一页上的新条目 那么你想在底部滚动意味着你的最后一个单元格? 对最后一个单元格是。当用户在表格上向下滑动并请求下一页时。让 tableview 停留并显示下一页。 您是否使用分页来显示您的数据?你在我的回答中检查你的表格视图去你的最后一个单元格检查我更新的答案 这很有意义。让我试试并确认 【参考方案1】:

你正在设置

[self.moviesTableView setContentOffset:CGPointMake(0, self.searchController.searchBar.frame.size.height)];

在加载完成后调用的addSearchBar 方法中,在初始点设置内容偏移量。

还要管理你setupInfiniteScrollView 在哪里将子视图添加到 Tableview 中。

还有一点点逻辑上的变化

获取这个旧的 y 偏移位置

CGFloat oldOffset = self.moviesTableView.contentOffset.y;

加载后设置相同的Y位置更像

CGPoint new = CGPointMake(0, oldOffset);
 [self.moviesTableView setContentOffset:new];

【讨论】:

我没有得到你 谢谢你帮我修好了。在其他地方设置内容偏移量的愚蠢错误。我没有注意到 didLayoutSubviews 在表格滚动时被多次调用。在 layoutSubviews 我有 awn addSearchBar 功能。在其中,我在初始点偏移了我的搜索栏。【参考方案2】:

在你的

中添加行
if ([[NSThread currentThread] isMainThread])
        NSLog(@"In main thread--completion handler");

       [self.refreshControl endRefreshing];

       NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[YOURARRAY.count] - 1 inSection:0];
       [self.YOURTABLLENAME scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

       [self.loadingMoreView stopAnimating];
       [MBProgressHUD hideHUDForView:self.view animated:YES];
 

【讨论】:

【参考方案3】:

您需要在收到数据后使用动态插入行:

NSMutableArray *arrayOfInsertedIndexes = [NSMutableArray array]; 
NSInteger currentCount = self.yourOldData.count; 
for (int i =0; i < yourNewData.count; i++) 
 
      [arrayOfInsertedIndexes addObject:[NSIndexPath indexPathForRow:currentCount+i inSection:0]];

[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:arrayOfInsertedIndexes withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];

不要使用

[self.tableView reloadData];

【讨论】:

你已经用 arrayOfInsertedIndexes 值更新了你的答案。 插入索引的数组只是新数据而不是整个数据数组? @mparrish91 看看。【参考方案4】:

问题是 reloadData 后 contentSize 不会同步更改。你应该在 reloadData 之后调用 layoutIfNeeded。只有在 contentSize 改变之后

试试这个

//.....
 if ([[NSThread currentThread] isMainThread])
     NSLog(@"In main thread--completion handler");

     CGFloat oldOffset = self.moviesTableView.contentSize.height;
     [self.moviesTableView reloadData];
     [self.moviesTableView layoutIfNeeded];
     CGFloat onewOffset = self.moviesTableView.contentSize.height;
     CGPoint new = CGPointMake(0, onewOffset - oldOffset);

     [self.moviesTableView setContentOffset:new];
     [self.refreshControl endRefreshing];
     [self.loadingMoreView stopAnimating];
     [MBProgressHUD hideHUDForView:self.view animated:YES];
//.......

【讨论】:

【参考方案5】:

目标 C:

 NSIndexPath* ip = [NSIndexPath indexPathForRow:rowNumberHere inSection:sectionNumberHere];
[theTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO];

斯威夫特:

 let offset = CGPoint(x: 0, y: self.tableView.contentSize.height - self.tableView.frame.size.height + self.FOOTERHEIGHT);
 self.tableView.contentOffset = offset;

【讨论】:

以上是关于添加新数据时,Tableview 会滚动到顶部。无限滚动的主要内容,如果未能解决你的问题,请参考以下文章

将 TableView 标题粘贴到顶部,导致当用户向下滚动时标题不“交互”

单击 tableview 单元格时滚动到顶部搜索栏控制器

将“标签状态栏滚动到顶部”添加到 UIScrollView 中包含的 UITableView

自动滚动到顶部在 UITableView 中不起作用

呈现另一个视图控制器将 UITableView 滚动到顶部

使用大标题时 iOS 11 滚动到顶部无法正常工作