无需设置代理即可观察任何 UIScrollView
这个小库提供了一些实用类和辅助方法,用于观察 UIScrollView
中的滚动偏移量变化,而无需设置代理。
此外,还有一些辅助方法可以在跨越特定(动态确定)阈值时自动触发回调,并根据滚动偏移量自动显示/隐藏视图。
您可以调用一个便捷辅助方法来快速开始观察滚动偏移量变化:UIScrollView.observeContentOffsetChanges()
。
此方法返回一个 ScrollViewObserverCancellable
,您可以使用它来停止观察。如果您永远不会停止观察,您可以简单地忽略返回值。
警告:不要在回调闭包中强引用滚动视图,否则会导致循环引用。
// prints content offset changes for the next 10 seconds
let cancellable = scrollView.observeContentOffsetChanges { scrollView in
print(scrollView.contentOffset)
}
DispatchQueue.main.asyncAfter(.now() + 10) {
cancellable.cancel()
}
// there's also a version that doesn't take a scroll view as parameter
scrollView.observeContentOffsetChanges { [weak self] in
self?.doSomethingWhenWeScroll()
}
该便捷方法封装并跟踪 ScrollViewObserver
。您也可以自己跟踪。
class UIViewController {
var observer: ScrollViewObserver!
func viewDidLoad() {
super.viewDidLoad()
// here we manually track an observer object. We need to hold on to it, because
// when it is deallocated, the observing will stop
observer = ScrollViewObserver(scrollView: scrollView) { scrollView _
print(scrollView.contentOffset)
}
}
}
还有一个辅助方法可以跟踪何时跨越特定阈值,并且仅在跨越阈值时触发回调。 例如,这可以用于切换...
UIScrollView.monitorOffsetTreshold()
此方法返回一个 ScrollViewObserverCancellable
,您可以使用它来停止观察。如果您永远不会停止观察,您可以简单地忽略返回值。
警告:不要在回调闭包中强引用滚动视图,否则会导致循环引用。
// This prints "A" if we scrolled to the first half of the scroll view and "B" in the second half.
let cancellable = scrollView.monitorOffsetTreshold(tresholdProvider: { scrollView in
return scrollView.contentSize.height * 0.5
}, callback: { isOverTreshold in
if isOverTreshold {
print("A")
} else {
print("B"")
}
})
您还可以提供自定义: - contentOffsetProvider
,它告诉监视器滚动视图的位置。通常,默认实现是合适的。 - 自定义 visibilityProvider
,它告诉监视器是否跨越了阈值。 默认实现执行 offset > treshold
,通常是合适的。
便捷方法封装并跟踪一个 ScrollViewOffsetMonitor
对象。您也可以自己跟踪
class UIViewController {
var monitor: ScrollViewOffsetMonitor!
func viewDidLoad() {
super.viewDidLoad()
// here we manually track a monitor object. We need to hold on to it, because
// when it is deallocated, the observing will stop
monitor = ScrollViewOffsetMonitor(scrollView: scrollView,tresholdProvider: { scrollView in
return scrollView.contentSize.height * 0.5
}, callback: { isOverTreshold in
if isOverTreshold {
print("A")
} else {
print("B"")
}
})
}
}
有一个辅助类(和便捷方法)可以根据滚动视图中是否跨越了特定阈值,自动隐藏/显示视图(通过设置 alpha)。
例如,这可以用于在 header view 可见时隐藏 label。
UIScrollView.toggleVisibility()
UITableView.toggleVisibility()
UICollectionView.toggleVisibility()
这些方法返回一个 ScrollViewObserverCancellable
,您可以使用它来停止观察。如果您永远不会停止观察,您可以简单地忽略返回值。
警告:不要在回调闭包中强引用滚动视图,否则会导致循环引用。
// this will automatically hide the `someLabel` when we haven't scrolled past
// the top of `someOtherView`
let cancellable = scrollView.toggleVisibility(
of: someLabel,
style: .showWhenPastTreshold,
whenScrollingPast: someOtherView,
edge: .top)
// this will automatically hide `someLabel` when we scrolled past the bottom of `someOtherView`
scrollView.toggleVisibility(of: someLabel, style: .hideWhenPastTreshold, whenScrollingPast: someOtherView)
// this will automaticaly hide `someLabel` when we scrolled past row 1 of section 0
tableView.toggleVisibility(of: someLabel, whenScrollingPast: IndexPath(row: 1, section: 0)
// this will automatically show `someLabel` when we scrolled past row 1 of section 0
let cancelleble = collectionView.toggleVisibility(of: someLabel, style: .hideWhenPastTreshold, whenScrollingPast: IndexPath(row: 1, section: 0)
便捷方法封装并跟踪一个 ScrollViewVisibilityToggler
对象。您也可以自己跟踪
class UIViewController {
var toggler: ScrollViewVisibilityToggler!
func viewDidLoad() {
super.viewDidLoad()
// here we manually track a toggler object. We need to hold on to it, because
// when it is deallocated, the observing will stop
toggler = ScrollViewVisibilityToggler(scrollView: scrollView, viewToMonitor: someOtherView, viewToToggle: someLabel)
}
}
UINavigationItem 上有一些辅助方法,可以在滚动超过另一个视图时自动显示自定义 titleView。 还有一个辅助方法可以直接显示自定义字符串。
UINavigationItem.showCustomTitleView(_:whenScrollingPast:in)
适用于 scrollViews、table views 和 collection viewsUINavigationItem.showCustomTitle(_:whenScrollingPast:in)
适用于 scrollViews、table views 和 collection views// this will automatically show mylabel when scrolling past the the title label in our custom header
navigationItem.setCustomTitleView(myLabel, whenScrollingPast: myCustomHeaderView.titleLabel, in: tableView)
// this will automatically show "My Custom Title" when scrolling past the the title label in our custom header
navigationItem.showCustomTitle("My Custom Title", whenScrollingPasth myCustomheaderView.titleLabel, in: scrollView)