UIScrollView设置居中起始偏移时特定设备contentOffset出现微小误差怎么办
问题原因
- 该偏差不属于iOS Bug,是系统为了避免半像素渲染导致画面模糊,自动对UIScrollView的contentOffset做物理像素对齐的默认机制。
- 当设备scale为奇数、屏幕宽度为奇数时,你计算的半宽值
187.5pt对应物理像素为187.5 * 3 = 562.5,不属于整数像素,系统会自动修正为最接近的整数像素562,换算回pt就是562 / 3 ≈ 187.333,就出现了你观测到的偏差。
可落地的解决方案
方案1:提前对数值做像素对齐(推荐)
在设置contentInset和contentOffset之前,先把计算值对齐到物理像素,避免系统自动修正:
let scale = UIScreen.main.scale let rawHalfWidth = scrollView.bounds.size.width / 2.0 // 先转成物理像素取整,再转回pt let alignedHalfWidth = round(rawHalfWidth * scale) / scale scrollView.contentInset = UIEdgeInsets(top: 0, left: alignedHalfWidth, bottom: 0, right: alignedHalfWidth) scrollView.contentOffset = CGPoint(x: -alignedHalfWidth, y: 0)
后续计算滑动比例时直接用alignedHalfWidth作为基准值即可,不会出现偏差。
方案2:计算比例时增加误差容忍阈值
该偏差的最大值不会超过1/(2*scale) pt,以scale=3的设备为例最大偏差仅为0.1667pt,你可以在计算滑动比例时增加小阈值做兼容:
let expectedBaseOffset = -rawHalfWidth let actualOffset = scrollView.contentOffset.x let tolerance = 1 / (2 * UIScreen.main.scale) var scrollRate: CGFloat = 0 if abs(actualOffset - expectedBaseOffset) >= tolerance { // 正常计算滚动比例 scrollRate = (actualOffset - expectedBaseOffset) / (contentWidth - scrollView.bounds.width) } else { // 偏差在容忍范围内,直接判定为未滚动,比例为0 scrollRate = 0 }
内容的提问来源于stack exchange,提问作者Rohan Sanap
相关产品推荐
相关产品推荐

