【问题标题】:iOS UITableView Offset Refresh ControliOS UITableView 偏移刷新控件
【发布时间】:2019-02-06 22:48:04
【问题描述】:

我有一个受限于超级视图的 UITableView。所以第一个单元格位于超级视图的顶部。这意味着在 iPhone X 上,第一个单元格会在槽口下方流血,并进入状态栏区域。这是完全正确的。我希望单元格在槽口下方流血并进入状态栏区域,这是当前结果。

问题是,我还想在那个表格视图上设置一个刷新控件,以便用户可以拉动刷新内容。但是,当您在 iPhone X 上拉动刷新时,刷新控制会被缺口切断。我不希望刷新控制被缺口切断。

所以基本上我想要做的是将表格视图限制到超级视图,但将刷新控制限制在安全区域。

我看过了,Apple 似乎没有提供很多属性或方法来自定义刷新控件的行为。

我考虑过使用某种类型的自定义解决方案,但是我想到的每个自定义解决方案都会丢失刷新控件和表格视图滚动等所有预构建的物理特性。有太多的幕后逻辑,我真的不想牺牲拉动刷新的感觉以及用户的感觉,因为它已经成为 iOS 中如此普遍的动作。

关于如何让第一个单元格在缺口下流血(限制为超级视图)但确保刷新控制不会被缺口切断(限制在安全区域)的任何想法?

我还附上了下面的屏幕截图,说明单元格如何渗入状态栏,以及刷新控件如何被缺口切断。

编辑:我还向GitHub here发布了一个示例项目。

但刷新控件相关的基本代码如下。

private lazy var refreshControl = UIRefreshControl()
override func viewDidLoad() {
    super.viewDidLoad()

    refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
    tableView.refreshControl = refreshControl
}

@objc func handleRefresh() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
        self.refreshControl.endRefreshing()
    }
}

【问题讨论】:

  • 在添加加载视图时,您可以添加填充以防止出现此问题 (stackoverflow.com/questions/14856821/…) 另外,如果您为此发布代码,我们会更轻松地为您提供帮助跨度>
  • @RonakShah 不会也为内容本身添加填充吗?我刚刚使用示例项目 GitHub 存储库链接以及刷新控制代码编辑了问题。我真的不知道如何添加更多相关代码,因为此时它们都是非常标准的东西,而且大部分只是创建 UITableView 和界面的东西。
  • 尝试为那个UIViewController启用adjustScsrollViewInsets。根据UITableView 的外观,我想说他们在故事板中没有被选中

标签: ios swift uitableview uirefreshcontrol


【解决方案1】:

您可以从底层UIScrollView 中受益。通过您的 github 示例,您可以获得所需的一切,因此如果您使用以下方式扩展它:

extension ViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y < 0 {
            topConstraint.constant = -scrollView.contentOffset.y/2
        } else {
            topConstraint.constant = 0
        }
    }
}

每次contentOffset 开始低于0 并让您的tableView 移动到底部并且每当关闭或向下滚动时都会将其设置为默认值 - 在您的情况下为0

这样你最终会得到与拖动力/距离相关的平滑动画,如下所示

【讨论】:

    【解决方案2】:

    解决方案很简单,您可以在 viewDidLoad 中设置刷新控件的边界。使用您需要的 y 偏移值(例如 50)

      refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
      refreshControl.bounds = CGRect(x: refreshControl.bounds.origin.x,
                                     y: 50,
                                     width: refreshControl.bounds.size.width,
                                     height: refreshControl.bounds.size.height)
      tableView.refreshControl = refreshControl
    

    更新:

    您可以在刷新开始时添加内容插入,并在结束时将其恢复。

      override func viewDidLoad() {
            super.viewDidLoad()
    
    
          refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
          refreshControl.bounds = CGRect(x: refreshControl.bounds.origin.x,
                                         y: -100,
                                         width: refreshControl.bounds.size.width,
                                         height: refreshControl.bounds.size.height);
          tableView.refreshControl = refreshControl
        }
    
        @objc func handleRefresh() {
          self.tableView.contentInset = UIEdgeInsets(top: 200, left: 0, bottom: 0, right: 0)
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
              self.refreshControl.endRefreshing()
              self.tableView.contentInset = UIEdgeInsets.zero
              self.tableView.setContentOffset(.zero, animated: true)
            }
        }
    

    【讨论】:

    • 这个方案的问题是,当释放拉取刷新时,内容会在加载指示器的下方,并且不会停留在加载指示器的下方,这使得加载指示器很难看到。跨度>
    • 查理,我已经更新了我的答案,在更新部分你可以看到你的问题的解决方案。
    • 添加内容插入也会降低加载指示器以及内容。不只是降低了内容,所以底层问题依然存在。
    • 你可以看看我是如何修复它的,我为刷新控制添加了负 y 偏移。
    • 在 viewDidLoad 检查 refreshControl.bounds 设置。
    【解决方案3】:

    表格视图的顶部约束必须相对于上边距

    【讨论】:

    • 这不是我想要的。正如我在问题Which means on the iPhone X that first cell bleeds under the notch, and into the status bar area. Which is exactly right. 中所说。我希望单元格渗入状态栏区域。但我不希望刷新控件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多