【问题标题】:Remembering scroll position on UITableView记住 UITableView 上的滚动位置
【发布时间】:2013-09-21 12:30:35
【问题描述】:

我在 xcode 中的 iOS 应用程序有点问题。我有一个加载几百个单元格的 UITableView。当我向下滚动到特定单元格并向下钻取到 detailviewcontrollers 并再次返回时,主视图表一直返回到顶部。我看过以下两个类似的问题。

How can I get the UITableView scroll position so I can save it?

Setting scroll position in UITableView

我仍然无法让这些工作。我不是最有经验的编码员,所以我真的很挣扎。

我知道需要更改 viewWillDisappear 和 viewDidAppear 之类的内容,但我真的无法再进一步了。

在这张表上,我有一个 reloadData 功能,因此可以从服务器和一个有效的搜索栏下拉最新数据。

无论如何,伸出援助之手会很棒。谢谢,

卢克

【问题讨论】:

  • 这不是默认行为。似乎您的代码中某处正在滚动到顶部。如果删除该行,则应该一切就绪。搜索scrollToRowAtIndexPath 可能。
  • 当您的表格重新回到视图中时,它很可能会滚动回顶部,因为您在该视图控制器的“viewWillAppear:”方法中对其进行了“reloadData”调用。

标签: ios uitableview uiviewcontroller reloaddata viewdidappear


【解决方案1】:

看到这里你必须先保存tableView的滚动位置,即tableView的contentOffset,然后当你回到tableView时重新使用它。

1) 保存时间和地点:

何时:此时,当您向下钻取到 detailViewController 时,保存 tableView 的 contentOffset

如何:float verticalContentOffset = tableView.contentOffset.y;

2) 如何将 tableView 设置回相同的滚动位置:

[tableView setContentOffset:CGPointMake(0, verticalContentOffset)];

希望这会对您有所帮助。

【讨论】:

  • 关于如何为消息传递应用程序实现这一点的任何想法?与向上滚动加载更多行一样,但当前 Y 偏移量始终为 0。这意味着将 contentOffset 设置为 Y = 0 只会将该表再次滚动到顶部
【解决方案2】:

排序!

在 Desdenova 的启发下,我在工作中好好思考并意识到它可能是什么。记得我有一个搜索栏,几个月前我实现了以下代码来隐藏它:

[self.tableView setContentOffset:CGPointMake(0,-20) animated:NO];

天真地我把它放在viewDidAppear而不是viewDidLoad。显然,这确实隐藏了搜索栏,但是由于它位于错误的 void 命令中,因此每次 masterDetailView 返回到堆栈顶部时都会这样做。所以,在将上面的代码移动到 viewDidLoad 之后,它现在仍然隐藏它,但只有一次。

我只是为像我这样的其他初学者这样拼写出来,他们可能会遇到同样的问题,可能只是为了挽救他们的理智!

感谢大家的想法帮助了我。

+1 给大家!

【讨论】:

  • 完美。谢谢。
【解决方案3】:

如果有人想知道,我尝试了 Prashant N 的解决方案,它奏效了。但是reloadData 现在实际上不再重置滚动位置,所以除了reloadData 之外我不需要做任何事情。

【讨论】:

    【解决方案4】:

    我对这个问题的解决方案是将表格滚动到最后一项的索引行。

    private func scrollToItem(item:Int, section:Int bottom:Bool = true, animated:Bool = false) {
        let indexPath = NSIndexPath(forRow: item:Int-1, inSection: section)
        var position = UITableViewScrollPosition.Bottom
        if (!bottom) { position = UITableViewScrollPosition.Top }
        self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: position, animated: animated)
    }
    

    【讨论】:

      【解决方案5】:

      由于某种原因,这对我来说是一半(有时该位置只是近似值)。我终于使用了以下先验不太干净的解决方案

      NSIndexPath *firstVisibleIndexPath = [[self.tableView indexPathsForVisibleRows] objectAtIndex:0];
      [self.tableView scrollToRowAtIndexPath:self.firstVisibleIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
      self.firstVisibleIndexPath = firstVisibleIndexPath;
      

      哪个效果更好。

      【讨论】:

      • 一个相当漫长的路线方法,但应该很好用。为什么将索引路径存储为实例变量?我认为这只是您项目的特定内容?
      • 好吧,我以为我回答的问题略有不同,这是针对具有分段控件和 2 个分段的用例。因此,当您切换段时,您会保存 indexPath 以供下次您进入该段时使用(注意属性是在滚动完成后设置的)
      • 当您停留在屏幕上并通过上下滚动来玩 tableview 时,这是否会更新 firstVisibleIndexPath?当表格滚动时,您在哪个事件或委托方法中连续更新firstVisibleIndexPath?
      【解决方案6】:

      正如在其他 cmets 中提到的,在 UINavigationController 中滚动到返回导航的顶部不是默认行为。

      另一个原因可能是您将表格顶部附近的一个单元格设置为 viewWillAppear 中的第一响应者,例如靠近表格顶部的搜索框或编辑字段。 UITableViewController 会自动将第一响应者滚动到视图中,这很好。只要那是你想要做的。 :) 注意不要在 viewWillAppear 中设置第一响应者,除非那是你想要的。干杯,亚利桑那州

      【讨论】:

        【解决方案7】:

        我的收藏决定:

        CGFloat oldCollectionViewHeight = self.messageCollectionView.contentSize.height;
        
        [self.messageCollectionView reloadData];
        [self.messageCollectionView layoutIfNeeded];
        
        CGFloat newCollectionViewHeight = self.messageCollectionView.contentSize.height;
        
        if (oldCollectionViewHeight) {
            self.messageCollectionView.contentOffset = CGPointMake(0, newCollectionViewHeight - oldCollectionViewHeight);
        }
        

        对于表,原理是一样的。

        【讨论】:

          【解决方案8】:

          你不需要做任何事情,当你在同一个视图控制器中时,你的位置是一样的。恐怕您的视图控制器中的某个地方被称为 reloadData。搜索一些调用 scrollToRowAtIndexPath 的方法。

          【讨论】:

          • 是的,我把它整理好了。解决方案在接受的答案中。
          猜你喜欢
          • 1970-01-01
          • 2014-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-11
          • 2012-09-26
          • 1970-01-01
          相关资源
          最近更新 更多