您可以通过使用键值观察(KVO)来同时实现这两个目标,独立于表视图委托监视contentOffset
和contentSize
。
contentOffset
是scrollView已滚动的量。 y
值是垂直方向上滚动的量。
contentSize
是所有表行的总高度。
KVO允许您编写代码,每当另一个对象上的属性更改时调用该代码。 您可以使用KVO来监视contentSize
和contentOffset
的更改,并在这些值更改时更新自定义视图。
以下是在CocoaPod中实现它的方式:
private var ContentOffsetKVO = 0
private var ContentSizeKVO = 0
public class ScrollController: NSObject {
public var customView: UIView? {
didSet {
updateScrollPosition()
}
}
public var scrollView: UIScrollView? {
didSet {
if let view = oldValue {
removeKVO(view)
}
if let view = scrollView {
addKVO(view)
updateScrollPosition()
}
}
}
deinit {
if let scrollView = scrollView {
removeKVO(scrollView)
}
}
private func removeKVO(scrollView: UIScrollView) {
scrollView.removeObserver(
self,
forKeyPath: "contentSize",
context: &ContentSizeKVO
)
scrollView.removeObserver(
self,
forKeyPath: "contentOffset",
context: &ContentOffsetKVO
)
}
private func addKVO(scrollView: UIScrollView) {
scrollView.addObserver(
self,
forKeyPath: "contentSize",
options: [.Initial, .New],
context: &ContentSizeKVO
)
scrollView.addObserver(
self,
forKeyPath: "contentOffset",
options: [.Initial, .New],
context: &ContentOffsetKVO
)
}
public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
switch keyPath {
case .Some("contentSize"), .Some("contentOffset"):
self.updateScrollPosition()
default:
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
}
private func updateScrollPosition() {
guard let scrollView = scrollView, let customView = customView else {
return
}
let viewSize = scrollView.bounds.size.height
let scrollLimit = scrollView.contentSize.height - viewSize
let scrollOffset = scrollView.contentOffset.y
let scrollDelta = scrollOffset / scrollLimit
let trackerFrame = customView.frame
let trackerTravel = viewSize - trackerFrame.size.height
let trackerOffset = scrollOffset + (trackerTravel * scrollDelta)
customView.frame = CGRect(
origin: CGPoint(
x: 0,
y: trackerOffset
),
size: trackerFrame.size
)
}
}
使用方法:
let scrollController = ScrollController()
override func viewDidLoad() {
super.viewDidLoad()
scrollController.scrollView = tableView
let customView = UIView(
frame: CGRect(
origin: CGPointZero,
size: CGSize(
width: 44,
height: 44
)
)
)
customView.backgroundColor = UIColor.magentaColor()
tableView.addSubview(customView)
scrollController.customView = customView
}
Swift2
标签仅针对迁移问题。但这似乎不是该情况,因此只使用swift
标签即可。 - Alonso Urbano