iOS:UIScrollView 不会对所有值进行采样



我想具体知道滚动视图的偏移量何时到达页面中心。不幸的是,scrollViewDidScroll不会对所有值进行采样。所以我不是每次经过屏幕中央时都进入if。我怎样才能克服这个问题?

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
let offsetInPage = (scrollView.contentOffset.x / scrollView.frame.size.width) - CGFloat(page)
if offsetInPage == 0.5 { // Does not called every time
toggleColors()
}
}
contentOffset

通过处理触摸手势来更新,这无法连续完成,因为它不像您在每次更改时都从触摸屏接收消息,而是系统正在检查触摸屏的状态在某个循环中。在这种情况下,它是运行循环。因此,在运行循环迭代之间可能会发生一些更改,并且应用程序不会捕获这些更改。从理论上讲,在某些情况下,差距甚至可能超过整个页面。

因此,最好检查一下现在可见的区域,并计算当该区域可见时应该应用什么颜色,而不是等待出现某个确切的contentOffset

根据您的代码,您似乎只想在用户滚动时切换颜色,以便所有奇数页都具有一种颜色,而所有偶数页 - 另一种颜色。如果是这样,我会这样做:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
let isOddPage = (page % 2 == 1)
let offsetInPage = (scrollView.contentOffset.x / scrollView.frame.size.width) - CGFloat(page)
if (isOddPage && offsetInPage < 0.5) || (!isOddPage && offsetInPage >= 0.5) {
switchToOddColor()
} else {
switchToEvenColor()
}
}

或类似的东西。也许您的情况更复杂,也许您不止两种颜色,但策略是相同的。

检查颜色是否尚未在switchToOddColor中设置为所需的值也很有用,switchToEvenColor以避免执行额外的工作。

我建议您 1) 检查一个表示页面偏移量是否大于一半的值,并且 2) 仅在值更改时才切换颜色:

var isOverHalf: Bool = true
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
let offsetInPage = (scrollView.contentOffset.x / scrollView.frame.size.width) - CGFloat(page)
let isOverHalf = offsetInPage > 0.5
If self.isOverHalf != isOverHalf {
toggleColors()
}
self.isOverHalf = isOverHalf
}

也许这是一种不需要的答案,这里也是 RxSwift 版本:

scrollView.rx.didSCroll
.map { [weak scrollView] _ in scrollView?.offsetInPage ?? 0 }
.map { $0 > 0.5 }
.distinctUntilChanged() // this line prevents toggleColors() from being called for the same values multiple times
.subscribe(onNext: { [weak self] _ in
self?.toggleColors()
})
.disposed(by: disposeBag)
extension UIScrollView {
var offsetInPage: CGFloat {
let page = contentOffset.x / frame.size.width
return page - floor(page)
}
}

由于您使用浮点数进行比较,我建议使用如下所示的范围:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
let offsetInPage = (scrollView.contentOffset.x / scrollView.frame.size.width) - CGFloat(page)
if (0.45..<0.55).contains(offsetInPage) {
print("near to center")
toggleColors()
}
}

scrollViewDidScroll这样的函数不能在每个浮点值上触发,因为这是不可能的!您需要像上面一样检查或尝试lowerValuebiggerValue捕获 2 个值。

最新更新