You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 10下如何模拟adjustedContentInset计算UITableView相对滚动量?

iOS 10 下等效于 adjustedContentInset 的相对滚动量计算

这个问题在iOS 10及更早版本确实很常见——系统自动调整滚动视图的偏移量时,首次scrollViewDidScroll(_:)调用会出现非预期的contentOffset跳变,导致我们无法直接用原始偏移量计算相对滚动距离。下面是具体的解决思路和代码实现:

核心思路

在iOS 10及以下版本,当UITableView处于UINavigationController内且automaticallyAdjustsScrollViewInsets为true时,系统会在视图布局完成后(viewDidLayoutSubviews阶段)自动给tableView设置contentInset.top,其值等于状态栏高度 + 导航栏高度。我们只需要提前获取这个初始的顶部偏移基准,再用实时的contentOffset.y减去它,就能得到和iOS 11中adjustedContentInset等效的相对滚动量。

完整代码实现

首先定义一个属性存储初始的顶部偏移基准:

private var initialTopOffset: CGFloat = 0.0

然后在viewDidLayoutSubviews中获取这个基准值(确保只获取一次,避免重复计算):

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    guard initialTopOffset == 0 else { return }
    
    if #available(iOS 11.0, *) {
        initialTopOffset = tableView.adjustedContentInset.top
    } else {
        // 分两种情况处理:系统自动调整或手动调整
        if tableView.automaticallyAdjustsScrollViewInsets {
            initialTopOffset = tableView.contentInset.top
        } else {
            // 手动计算状态栏+导航栏高度
            let statusBarHeight = UIApplication.shared.statusBarFrame.height
            let navBarHeight = navigationController?.navigationBar.frame.height ?? 0.0
            initialTopOffset = statusBarHeight + navBarHeight
        }
    }
}

最后在scrollViewDidScroll(_:)中计算相对滚动量:

override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let deltaY = scrollView.contentOffset.y - initialTopOffset
    // 这里使用deltaY来修改你的单元格子视图尺寸和位置即可
}

为什么这么做?

在iOS 10中,viewDidLoad阶段tableView的布局还未完成,系统还没来得及调整contentInset,所以此时contentOffset是CGPointZero;而到了首次scrollViewDidScroll(_:)调用时,系统已经完成了布局调整,contentOffset.y会跳至initialTopOffset的值,这就是你看到的非零偏移。用实时偏移量减去这个基准值后,deltaY会从0开始变化,完全符合我们预期的相对滚动逻辑。

内容的提问来源于stack exchange,提问作者Andy Obusek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:58:58