UIScrollView contenttoffset值略微错误



我的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中,数据值如下:

  • ViewController/Screen/scrollViewwidth =390
  • halfWidth=195
  • scrollView.contentOffset.x=-195

以上所有的值都是绝对正确的,根据我们在代码中的计算。

不工作的地方

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

  • ViewController/Screen/scrollViewwidth =375
  • halfWidth=187.5
  • scrollView.contentOffset.x=-187.33333333333334

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

用其他设备进一步观察

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

  • 条件1:设备宽度为奇数
  • 条件2:设备比例因子为奇数。

复制错误的设备示例- iPhone 12 mini, 11 Pro, X, XS。这些器件的屏幕宽度为375,比例系数为3

为什么精度很重要

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

这是一个已知的错误吗?有什么方法可以解决这个问题吗?

我已经创建了一个示例项目用于快速调试。你可以从这里克隆它。

操作系统将把你的控件放在一个偶数像素的边界上。

您正在UI空间中定位控件。所以系统会将你提供的坐标转换为像素空间,设置控件的位置(在像素边界上),但在UI空间中返回位置给你。

它将你在UI空间中的偏移量转换为像素空间

offset * screen scale = pixel offset

187.5 * 3 = 562.5像素

但是像素是真实的,物理的东西。没有所谓的半像素。因此,系统四舍五入,像素偏移量变为562像素。

当你把偏移量转换回UI空间

像素偏移/屏幕比例= UI空间偏移

562/3 = 187.3333…

这就是为什么系统会返回这个值。

最新更新