【问题标题】:UITableView contentOffSet is not working properlyUITableView contentOffSet 无法正常工作
【发布时间】:2013-03-05 11:05:57
【问题描述】:

viewWillAppear 中,我添加了UISearchBar 作为UITableView 的标题视图。当视图加载时,我使用 UITableView 的 contentOffSet 将 UISearchbar 隐藏在 UINavigationBar 下。当用户下拉表格视图时,搜索栏就会显示出来。

添加 headerview 后,我使用以下代码将其隐藏。

self.tableView.contentOffset = CGPointMake(0, 40); //My searhbar height is 40

但有时contentOffSet 并没有隐藏标题视图。可能是什么错误。

【问题讨论】:

  • 你试过打电话给setContentOffset:animated:吗?
  • 我尝试了 setContentOffset:animated:,但它没有按预期工作
  • 你设置了headerview的高度吗?
  • 是的,headerview 高度是 40。我也检查了日志
  • 你的桌框是什么?

标签: iphone ios uitableview contentoffset


【解决方案1】:

这对我有用:

// contentOffset will not change before the main runloop ends without queueing it, for iPad that is
dispatch_async(dispatch_get_main_queue(), ^{
    // The search bar is hidden when the view becomes visible the first time
    self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.searchBar.bounds));
});

把它放在你的 -viewDidLoad 或 -viewWillAppear 中

【讨论】:

  • 对我来说,这是该主题的最佳答案。这不是“hacky”
  • 也适用于我。就像在 Android 中一样,你需要在 onCreate() 方法中使用 postDelayed()。
【解决方案2】:

不确定是什么原因(现在没时间研究),但我在延迟 0 后使用performSelector 解决了这个问题。示例:

- (void)viewWillAppear:(BOOL)animated {
    ...
    [self performSelector:@selector(hideSearchBar) withObject:nil afterDelay:0.0f];
}

- (void)hideSearchBar {
    self.tableView.contentOffset = CGPointMake(0, 44);
}

【讨论】:

  • 谢谢,效果很好。我在 viewDidLoad 中使用了它,这样当用户弹出时 tableview 不会改变。
  • 您曾经诊断过这个问题吗?这个修复也为我解决了这个问题,但我很想知道根本问题是什么。这似乎更像是一种解决方法。谢谢!
  • 这个答案真的很巧妙。我会冒险猜测 tableview 在创建期间设置它自己的内容偏移量,但在将其放置在视图上之前,因此会覆盖您的内容偏移量。通过 performSelector 它在内部方法调用之后将其堆叠起来,因此它可以工作(虽然只是一个猜测)
【解决方案3】:

在早期版本的 iOS SDK 中,viewWillAppear 等方法在主线程上运行,现在它们在后台线程上运行,这就是现在出现问题的原因。

大多数回调倾向于在后台线程上触发,因此在进行 UI 调用时始终检查线程安全。

将更改分发到主线程上的内容偏移量:

目标 C

dispatch_async(dispatch_get_main_queue(), ^{
    CGPoint offset = CGPointMake(0, self.searchBar.bounds.height)
    [self.tableView setContentOffset:offset animated:NO];
});

斯威夫特 3

DispatchQueue.main.async {
            let offset = CGPoint.init(x: 0, y: self.searchBar.bounds.height)
            self.tableView.setContentOffset(offset, animated: false)
        }

【讨论】:

  • 非常感谢,终于经过这么多看似逻辑的调整以使我的表头按要求消失,这个简单的代码工作,欢呼!
  • 谢谢哥们....但是为什么呢?我以前从未像这样更改过偏移量,我不明白这样做的真正原因。我的意思是它有效,但我不知道为什么
  • 在早期版本的 iOS SDK 中,viewWillAppear 等方法在主线程上运行,现在它们在后台线程上运行,这就是现在出现问题的原因。大多数回调往往在后台线程上触发,因此在进行 UI 调用时始终检查线程安全。
  • 这里的推理是“viewWillAppear 在后台线程上运行”,这是错误的说法。所有 UIKit 都只是主线程。因此,在主线程上使用调度并没有真正的帮助(因为它已经在主线程上),但由于时间变化而有所帮助。
【解决方案4】:

这对我有用。

self.tableView.beginUpdates()
self.tableView.setContentOffset( CGPoint(x: 0.0, y: 0.0), animated: false)
self.tableView.endUpdates()

Objective-C:

[_tableView beginUpdates];
[_tableView setContentOffset:CGPointMake(0, 0)];
[_tableView endUpdates];

【讨论】:

  • 为我工作。 IOS 11. 只需输入 [yourSuperbTableView beginUpdates];等等,对于 Obj-C。
  • 请注意,beginUpdates 调用旨在为表格准备内容更改,例如删除或添加行,而不是简单的 UI 操作。您在这里可以摆脱它,因为这些类型的更新调用将假设在 endUpdates 之后 UI 发生变化(例如行动画)。不要依赖此调用来进行您自己的自定义 UI 更改。
【解决方案5】:

我用 layoutIfNeeded()

修复了它
    self.articlesCollectionView.reloadData()
    self.articlesCollectionView.layoutIfNeeded()
    self.articlesCollectionView.setContentOffset(CGPoint(x: 0, y: 40), animated: false)

【讨论】:

    【解决方案6】:

    在我的情况下,问题是我打电话

     [_myGreatTableView reloadData];
    

    在获得_tableView.contentOffset.y 之前。这总是返回“0”。

    所以我切换了这些方法的顺序,现在它可以工作了。

    在我看来这是一个很奇怪的行为,因为 offset 返回 0 但 UI 仍然保持表格的滚动位置。

    【讨论】:

      【解决方案7】:

      这可能是因为 View Controller 上的“Adjust Scroll View Insets”属性。 看到这个:https://stackoverflow.com/a/22022366

      编辑: 请务必检查 'contentInset' 的值以查看发生了什么,因为这也会对滚动视图产生影响。 此值在 viewWillAppear: 设置后更改,这似乎是其他人试图通过使用调度队列等来避免的。

      【讨论】:

      • 添加了更多信息,因为由于某种原因,答案被否决了。
      【解决方案8】:

      经过一小时的测试,唯一能 100% 工作的方法是:

      -(void)hideSearchBar
      {
          if([self.tableSearchBar.text length]<=0 && !self.tableSearchBar.isFirstResponder)
          {
              self.tableView.contentOffset = CGPointMake(0, self.tableSearchBar.bounds.size.height);
              self.edgesForExtendedLayout = UIRectEdgeBottom;
          }
      }
      
      -(void)viewDidLayoutSubviews
      {
          [self hideSearchBar];
      }
      

      使用这种方法,如果搜索栏为空,您始终可以隐藏搜索栏

      【讨论】:

      • 完美运行,就我而言,我必须添加 [self hideSearchBar];在视图中会出现
      【解决方案9】:

      问题是自动屏蔽。选择您的表格并确保您已选择所有行,如下图所示。

      【讨论】:

      • 你有没有在你的 xib 中尝试过这个东西并删除所有 contentoffset 代码
      【解决方案10】:

      这行代码正在正常工作。

      contentOffsetUITableView的解释:

      例如,如果您有一个高度为 100 的表格视图。它的内容可能比它的视图多,例如 150。contentOffset 将告诉表格从内容中的哪个位置开始。说contentOffset = (0, 40),内容将在其高度的40之后显示。

      注意:一旦内容滚动,就不再影响之前设置的contentOffset

      【讨论】:

        【解决方案11】:

        滚动表格时需要自己隐藏搜索栏。所以不要把它作为UITableView 标头。您可以通过将其高度设置为零来隐藏它。这样,如果您的表格视图设置为自动调整大小,它将展开。

        【讨论】:

          【解决方案12】:

          问题可能与搜索栏大小有关。试试下面这行代码。

          [searchBar sizeToFit];
          

          【讨论】:

            【解决方案13】:

            如果您的表格总是至少有一行,只需滚动到表格的第一行,搜索栏就会自动隐藏。

            let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
            

            self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)

            如果你把上面的代码放在viewDidLoad上,会抛出一个错误,因为tableView还没有加载,所以你必须把它放在viewDidAppear,因为通过此时 tableView 已经加载。

            如果你把它放在viewDidAppear上,每次打开tableView它都会滚动到顶部。

            如果 tableView 保持打开状态,例如当它是 UITabBar 视图控制器或执行 segue 然后返回时,您可能不希望出现这种行为。如果您只想让它在初始加载时滚动到顶部,您可以创建一个变量来检查它是否是初始加载,以便它只滚动到顶部一次。

            首先在视图控制器类中定义一个名为isInitialLoad的变量,并将其设置为“true”:

            var isInitialLoad = true
            

            然后检查 viewDidAppear 上的 isInitialLoad 是否为 true,如果为 true,则滚动到顶部并将 isInitialLoad 变量设置为 false:

            if isInitialLoad {
                let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
                self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)
                isInitialLoad = false
            }
            

            【讨论】:

              【解决方案14】:

              在 iOS 7/8/9 中简单的 self.automaticallyAdjustsScrollViewInsets = NO;解决了我的问题

              【讨论】:

              【解决方案15】:
              self.tableView.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height -80, 0, 0, 0);
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2019-04-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-04-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多