Scrollview 动画时获取偏移量
Get offset when Scrollview is animated
我有一个带动画的滚动视图
UIView.animate(withDuration: Double(totalMidiTime) / 1000, delay: 0, options: .curveLinear) {
self.scrollView.contentOffset.x = self.scrollView.contentSize.width - self.leftMargin
} completion: { (_) in }
我想在动画时获取当前位置偏移量
您可以通过检查滚动视图的 presentation layer:
的 bounds.origin.x
值来获取偏移量
guard let pl = scrollView.layer.presentation() else {
return
}
print("Content Offset X:", pl.bounds.origin.x)
这是一个完整的例子...
我们创建了一个包含 30 个标签的滚动视图。在 viewDidAppear
上,我们开始一个 20 秒的水平动画到最后一个标签。每次我们点击按钮时,“状态标签”将更新为滚动视图表示层的当前 bounds.origin.x
(与 contentOffset.x
匹配):
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .systemGreen
return v
}()
let testButton: UIButton = {
let v = UIButton()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .blue
v.setTitle("Get Offset", for: [])
v.setTitleColor(.lightGray, for: .highlighted)
return v
}()
let statusLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.numberOfLines = 0
v.textAlignment = .center
v.text = "Content Offset X\n0.00"
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
let stack = UIStackView()
stack.distribution = .fillEqually
stack.spacing = 8
stack.translatesAutoresizingMaskIntoConstraints = false
for i in 1...30 {
let v = UILabel()
v.backgroundColor = .yellow
v.text = "Label \(i)"
v.textAlignment = .center
stack.addArrangedSubview(v)
}
scrollView.addSubview(stack)
view.addSubview(scrollView)
view.addSubview(testButton)
view.addSubview(statusLabel)
let g = view.safeAreaLayoutGuide
let cg = scrollView.contentLayoutGuide
let fg = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
scrollView.heightAnchor.constraint(equalToConstant: 60.0),
stack.topAnchor.constraint(equalTo: cg.topAnchor, constant: 8.0),
stack.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 8.0),
stack.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -8.0),
stack.bottomAnchor.constraint(equalTo: cg.bottomAnchor),
stack.heightAnchor.constraint(equalTo: fg.heightAnchor, constant: -16.0),
testButton.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 20.0),
testButton.centerXAnchor.constraint(equalTo: g.centerXAnchor),
testButton.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.6),
statusLabel.topAnchor.constraint(equalTo: testButton.bottomAnchor, constant: 20.0),
statusLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
statusLabel.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.9),
])
testButton.addTarget(self, action: #selector(gotTap(_:)), for: .touchUpInside)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 20.0, delay: 0, options: .curveLinear) {
self.scrollView.contentOffset.x = self.scrollView.contentSize.width - self.scrollView.frame.width
} completion: { (_) in }
}
@objc func gotTap(_ sender: UIButton) -> Void {
guard let pl = scrollView.layer.presentation() else {
return
}
let x = String(format: "%0.2f", pl.bounds.origin.x)
statusLabel.text = "Content Offset X\n\(x)"
}
}
我有一个带动画的滚动视图
UIView.animate(withDuration: Double(totalMidiTime) / 1000, delay: 0, options: .curveLinear) {
self.scrollView.contentOffset.x = self.scrollView.contentSize.width - self.leftMargin
} completion: { (_) in }
我想在动画时获取当前位置偏移量
您可以通过检查滚动视图的 presentation layer:
的bounds.origin.x
值来获取偏移量
guard let pl = scrollView.layer.presentation() else {
return
}
print("Content Offset X:", pl.bounds.origin.x)
这是一个完整的例子...
我们创建了一个包含 30 个标签的滚动视图。在 viewDidAppear
上,我们开始一个 20 秒的水平动画到最后一个标签。每次我们点击按钮时,“状态标签”将更新为滚动视图表示层的当前 bounds.origin.x
(与 contentOffset.x
匹配):
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .systemGreen
return v
}()
let testButton: UIButton = {
let v = UIButton()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .blue
v.setTitle("Get Offset", for: [])
v.setTitleColor(.lightGray, for: .highlighted)
return v
}()
let statusLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.numberOfLines = 0
v.textAlignment = .center
v.text = "Content Offset X\n0.00"
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
let stack = UIStackView()
stack.distribution = .fillEqually
stack.spacing = 8
stack.translatesAutoresizingMaskIntoConstraints = false
for i in 1...30 {
let v = UILabel()
v.backgroundColor = .yellow
v.text = "Label \(i)"
v.textAlignment = .center
stack.addArrangedSubview(v)
}
scrollView.addSubview(stack)
view.addSubview(scrollView)
view.addSubview(testButton)
view.addSubview(statusLabel)
let g = view.safeAreaLayoutGuide
let cg = scrollView.contentLayoutGuide
let fg = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
scrollView.heightAnchor.constraint(equalToConstant: 60.0),
stack.topAnchor.constraint(equalTo: cg.topAnchor, constant: 8.0),
stack.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 8.0),
stack.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -8.0),
stack.bottomAnchor.constraint(equalTo: cg.bottomAnchor),
stack.heightAnchor.constraint(equalTo: fg.heightAnchor, constant: -16.0),
testButton.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 20.0),
testButton.centerXAnchor.constraint(equalTo: g.centerXAnchor),
testButton.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.6),
statusLabel.topAnchor.constraint(equalTo: testButton.bottomAnchor, constant: 20.0),
statusLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
statusLabel.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.9),
])
testButton.addTarget(self, action: #selector(gotTap(_:)), for: .touchUpInside)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 20.0, delay: 0, options: .curveLinear) {
self.scrollView.contentOffset.x = self.scrollView.contentSize.width - self.scrollView.frame.width
} completion: { (_) in }
}
@objc func gotTap(_ sender: UIButton) -> Void {
guard let pl = scrollView.layer.presentation() else {
return
}
let x = String(format: "%0.2f", pl.bounds.origin.x)
statusLabel.text = "Content Offset X\n\(x)"
}
}