我想在用户滚动时在scrollIndicator上获取它的元素。 因此,更清楚地说,当用户滚动时,我要获取被拖动的元素(位于scoll指示器处)。
我的滚动视图是水平的。
提前谢谢
答案 0 :(得分:1)
如果您想在用户开始拖动某物时获取位置,则可以通过实现willBeginDragging
通过以下方式实现。
extension ViewController : UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
let location = scrollView.panGestureRecognizer.location(in: scrollView)
print(location)
}
}
答案 1 :(得分:1)
根据您的描述,所有您的scrollView子视图将具有相同的大小,并且每个子视图都将成为scrollView框架的大小。
使用该假设,基本思想是获取scrollView的contentOffset
,除以scrollView的宽度,然后将其转换为Int
,以获取子视图的“索引”正在显示。
因此,如果您的scrollView宽度为100点,则您添加的每个图像视图的宽度将为100点。如果用户已滚动,则contentOffset
为20
(向左滚动一点),索引将为:
Int(20.0 / 100.0) // equals 0
如果用户滚动到第三张图像的末尾,则contentOffset
将是315
,例如,索引将是:
Int(315.0 / 100.0) // equals 3
(当然,使用基于零的标准索引)
这是一个基本示例-代码中添加了所有元素,因此只需在Storyboard中使用空的ViewController并将其分配给该类:
class ScrollIndexViewController: UIViewController, UIScrollViewDelegate {
var theScrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
// array of colors for imageView backgrounds
// could be array of images (or image names), for example
var colors: [UIColor] = [
.red,
.green,
.blue,
.orange,
.magenta,
.yellow,
.brown,
.cyan,
.purple,
]
override func viewDidLoad() {
super.viewDidLoad()
// add the scroll view
view.addSubview(theScrollView)
// constrain it to the full view
NSLayoutConstraint.activate([
theScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0),
theScrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0.0),
theScrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0.0),
theScrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0.0),
])
// set scroll view delegate to self
theScrollView.delegate = self
// var to use when constraining the scrollable subviews
var prevImageView: UIImageView?
// for each element in the array
for cl in colors {
// create a new image view
let v = UIImageView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = cl
// add it to the scroll view
theScrollView.addSubview(v)
// all added image views get
// width = scroll view width
// height = scroll view height
// top = scroll view top
NSLayoutConstraint.activate([
v.widthAnchor.constraint(equalTo: theScrollView.widthAnchor, multiplier: 1.0),
v.heightAnchor.constraint(equalTo: theScrollView.heightAnchor, multiplier: 1.0),
v.topAnchor.constraint(equalTo: theScrollView.topAnchor, constant: 0.0),
])
// if this is the first added image view,
// constrain leading to scroll view leading
if cl == colors.first {
NSLayoutConstraint.activate([
v.leadingAnchor.constraint(equalTo: theScrollView.leadingAnchor, constant: 0.0),
])
}
// if this is the last added image view,
// constrain trailing to scroll view trailing
if cl == colors.last {
NSLayoutConstraint.activate([
v.trailingAnchor.constraint(equalTo: theScrollView.trailingAnchor, constant: 0.0),
])
}
// if prevImageView is not nil, that means we've added
// an image view before this one, so,
// constrain leading to trailing of previous image view
if let pv = prevImageView {
NSLayoutConstraint.activate([
v.leadingAnchor.constraint(equalTo: pv.trailingAnchor, constant: 0.0),
])
}
// set prevImageView to this image view
prevImageView = v
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// if user scrolled by swiping
// calculate the "index" of the visible image view
let idx = getImageIndex(scrollView)
// do what you want with the index
print(#function, "Index: \(idx)")
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
// if user scrolls and stops (i.e. doesn't swipe and lift)
if !decelerate {
// calculate the "index" of the visible image view
let idx = getImageIndex(scrollView)
// do what you want with the index
print(#function, "Index: \(idx)")
}
}
func getImageIndex(_ scrollView: UIScrollView) -> Int {
// get the contentOffset
let offX = scrollView.contentOffset.x
// get the width of the scroll view
// (which is also the width of the image view subviews)
let svW = scrollView.frame.width
// return offset.x / image view width as an Int
return Int(offX / svW)
}
}
请紧记---如果用户向左滚动直到图像的左边缘只有一个像素宽度可见, 该图像 仍会被认为是“可见图像视图”。
您可能希望更改索引计算以返回“最可见”子视图,您可以执行以下操作:
return Int((offX / svW).rounded())
或者只有当下一个图像视图至少可见75%...满足您的需要时,