ios - 在最靠近滚动视图中心的视图数组中查找视图
问题描述
如何在 x 坐标最接近屏幕中心的子视图数组中找到视图?
这就是我所拥有的:
extension UIScrollView {
func scrollToView(view:UIView, animated: Bool) {
if let origin = view.superview {
let childStartPoint = origin.convert(view.frame.origin, to: self)
self.scrollRectToVisible(CGRect(x: childStartPoint.x, y: 0, width: 1, height: self.frame.height), animated: animated)
}
}
}
解决方案
您可以通过获取滚动视图的“虚拟中心”来找到“最接近中心”的子视图——即.contentOffset.x
框架宽度的加 1/2:
// get the "virtual center" of the scroll view
let scrollCenterX = scrollView.contentOffset.x + scrollView.frame.width * 0.5
然后,通过获取子视图中心和“虚拟中心”之间的最小差异来找到“中心”视图:
// find the subview with center.x closest to scrollCenterX
let closestToCenterView = viewsToTrack.min { a, b in abs(a.center.x - scrollCenterX) < abs(b.center.x - scrollCenterX) }
这是一个工作示例:
class CenterInScrollViewController: UIViewController {
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .systemYellow
return v
}()
var viewsToTrack: [UIView] = []
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
scrollView.heightAnchor.constraint(equalToConstant: 200.0),
scrollView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
])
let cg = scrollView.contentLayoutGuide
var prevView: UIView!
for i in 1...10 {
let v = UILabel()
v.text = "\(i)"
v.textAlignment = .center
v.backgroundColor = .cyan
v.layer.borderWidth = 1
v.layer.borderColor = UIColor.red.cgColor
v.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(v)
v.widthAnchor.constraint(equalToConstant: 120.0).isActive = true
v.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor).isActive = true
if i == 1 {
v.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 10.0).isActive = true
} else {
v.leadingAnchor.constraint(equalTo: prevView.trailingAnchor, constant: 40.0).isActive = true
}
if i == 10 {
v.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -10.0).isActive = true
}
viewsToTrack.append(v)
prevView = v
}
scrollView.delegate = self
}
func centerMiddleView() -> Void {
// make sure we have views to find the centers
guard viewsToTrack.count > 0 else {
return
}
// reset view backgrounds to cyan
viewsToTrack.forEach { $0.backgroundColor = .cyan }
// get the "virtual center" of the scroll view
let scrollCenterX = scrollView.contentOffset.x + scrollView.frame.width * 0.5
// find the subview with center.x closest to scrollCenterX
let closestToCenterView = viewsToTrack.min { a, b in abs(a.center.x - scrollCenterX) < abs(b.center.x - scrollCenterX) }
// make sure we found one
if let v = closestToCenterView {
// set its background to yellow
v.backgroundColor = .yellow
// animate its center to the center of the scroll view via contentOffset
UIView.animate(withDuration: 0.3, animations: {
self.scrollView.contentOffset.x = v.center.x - self.scrollView.frame.width * 0.5
})
} else {
print("No center view? This shouldn't happen...")
}
}
}
extension CenterInScrollViewController: UIScrollViewDelegate {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
centerMiddleView()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
// let DidEndDecelerating handle positioning,
// unless Dragging ended while "holding in-place"
if !decelerate {
centerMiddleView()
}
}
}
请注意,除非您从第一个和最后一个子视图中添加了足够的前导和尾随,否则您将无法将这两个视图居中。
推荐阅读
- firebase - GCM 到 FCM 迁移离子 v1
- javascript - 如何在vue js中循环遍历数组中的图像数组
- java - error: reached end of file while parsing in Android Studio
- mysql - 在新的 CentOS 7 安装上正确安装 MySQL 5.7 的问题
- vim - 如何用括号替换括号但在它们之间保留内容?
- html - 在 div 中垂直居中文本:display:flex 和 align-items:center 不起作用
- python - 数据帧的 Python 嵌套字典转换为 JSON
- graphite - table graphite.account_profile does not exist
- graphql - Prisma graphql updateNode 突变
- swift - self.tabBarController.selectedIndex 不调用 viewDidAppear