UIScrollView contentOffset 值略有错误

UIScrollView contentOffset value marginally wrong

我的 ViewController 中有一个 scrollViewscrollView 垂直居中放置,其宽度等于 ViewController 的宽度,高度等于 100。为了使 scrollView 可滚动,我为这个 scrollView 设置了一个任意的 contentSize,假设它是 (500, 100)。这有助于我的 scrollView 水平滚动。

我的要求是 scrollView 的内容从 scrollView 的水平中心开始。因此,我在上面设置了 contentInset 值。

let halfWidth = scrollView.bounds.size.width / 2.0
scrollView.contentInset = UIEdgeInsets(top: 0, left: halfWidth, bottom: 0, right: halfWidth)
scrollView.contentOffset = CGPoint(x: -halfWidth, y: 0)

记住,我的 scrollView 宽度等于 ViewController 宽度。因此,上述代码中的 halfWidth 值将与 view.bounds.width / 2.0.

相同

在哪里工作

在 iPhone 12 Pro 中,数据值如下所示:

根据我们在代码中的计算结果证明上述所有值都是绝对正确的。

哪里不行

在 iPhone 12 mini 中,数据值如下所示:

scrollView.contentOffset.x 的值本应是 -187.5,但实际上是 -187.33333333333334

进一步观察所有其他设备

在观察模式时,我意识到 contentOffset 值的边际误差出现在满足以下两个条件的特定设备上:

重现错误的示例设备 - iPhone 12 mini、11 Pro、X、XS。所有这些设备的屏幕宽度 375 和比例因子 3.

为什么精度很重要

我的用例是我正在使用 UICollectionView 创建一个自定义滑块,它负责根据已发生的滚动量发出滑动的值/分数。在我上面提到的问题细节中,场景是针对没有发生滚动的情况,因此我对发出的值/分数的期望是 0。但是,由于这个边际错误,每次用户尝试将其滚动到开头时,该值都会变成非零。

这是已知错误吗?有什么解决办法吗?

我已经创建了一个用于快速调试的示例项目。 You can clone it from here.

OS 会将您的控件放置在偶数像素边界上。

您正在将控件定位在 UI Space 中。所以系统会把你提供的坐标翻译成像素space,设置控件的位置(在像素边界上),但是return你的位置在UISpace.

所以它需要你在 UI space 中的偏移量并将其转换为像素 space:

偏移量 * 屏幕比例 = 像素偏移量

187.5 * 3 = 562.5 像素

但像素是真实的、有形的东西。没有半像素这样的东西。所以系统四舍五入,像素偏移量变成562像素。

当您将该偏移量转换回 UI space

像素偏移/屏幕比例=uispace偏移

562 / 3 = 187.3333...

这就是系统返回该值的原因。