swift - 滑块导致初始化的约束被恢复
问题描述
当我使用滑块时,它会恢复到原来的位置。我不知道增加函数中发生了什么导致它这样做。我想在我不希望它们删除的代码中保留初始化约束。我只想在用户更改对象的滑块值时不恢复到原始位置。你可以在 gif 中看到发生了什么。
import UIKit
class ViewController: UIViewController {
var slizer = UISlider()
var oldCons = [NSLayoutConstraint]()
var viewDrag = UIImageView()
var panGesture = UIPanGestureRecognizer()
var widthConstraints: NSLayoutConstraint?
var tim: CGFloat = 50.0
var slidermultiplier: CGFloat = 0.6
override func viewDidLoad() {
super.viewDidLoad()
widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
[viewDrag,slizer].forEach{
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
NSLayoutConstraint.activate([
slizer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
slizer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
slizer.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.2),
slizer.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
])
slizer.addTarget(self, action: #selector(increase), for: .valueChanged)
viewDrag.backgroundColor = .orange
viewDrag.frame = CGRect(x: view.center.x-view.frame.width * 0.05, y: view.center.y-view.frame.height * 0.05, width: view.frame.width * 0.1, height: view.frame.height * 0.1)
panGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.draggedView(_:)))
viewDrag.isUserInteractionEnabled = true
viewDrag.addGestureRecognizer(panGesture)
oldCons = [
viewDrag.centerYAnchor.constraint(equalTo: view.centerYAnchor),
viewDrag.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: tim),
viewDrag.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
widthConstraints!,
]
NSLayoutConstraint.activate(oldCons)
}
@objc func sliderr() {
NSLayoutConstraint.deactivate(oldCons)
oldCons = [
viewDrag.centerYAnchor.constraint(equalTo: view.centerYAnchor),
viewDrag.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -tim),
viewDrag.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
widthConstraints!,
]
NSLayoutConstraint.activate(oldCons)
}
@objc func draggedView(_ sender: UIPanGestureRecognizer) {
self.view.bringSubview(toFront: viewDrag)
let translation = sender.translation(in: self.view)
viewDrag.center = CGPoint(x: viewDrag.center.x + translation.x , y: viewDrag.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: self.view)
}
@objc func increase() {
slidermultiplier = CGFloat(slizer.value)
widthConstraints?.isActive = false
widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
widthConstraints?.isActive = true
}
}
解决方案
视图“恢复”的原因是因为您已经给出了 viewDrag 自动布局约束......但是在您的 draggedView 函数中,您明确设置了它的框架(使用 viewDrag.center = CGPoint(...))。
这不会改变它的约束,一旦你做其他事情来更新它,UIKit 就会根据它的约束重新定位/重新调整它的大小。
不设置 的.center
属性,而是viewDrag
为Leading 和CenterY(定位)创建变量约束,并更新它们的.constant
值以移动视图。
看看这个——里面有很多评论可以帮助你弄清楚:
class SlideViewController: UIViewController {
var slizer = UISlider()
var viewDrag = UIImageView()
var panGesture = UIPanGestureRecognizer()
// Width, Leading and CenterY constraints for viewDrag
var widthConstraints: NSLayoutConstraint!
var viewDragLeadingConstraint: NSLayoutConstraint!
var viewDragCenterYConstraint: NSLayoutConstraint!
var tim: CGFloat = 50.0
var slidermultiplier: CGFloat = 0.6
override func viewDidLoad() {
super.viewDidLoad()
[viewDrag,slizer].forEach{
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
NSLayoutConstraint.activate([
slizer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
slizer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
slizer.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.2),
slizer.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
])
slizer.addTarget(self, action: #selector(increase), for: .valueChanged)
viewDrag.backgroundColor = .orange
// no point setting a frame, since
// viewDrag has .translatesAutoresizingMaskIntoConstraints = false
//viewDrag.frame = CGRect(x: view.center.x-view.frame.width * 0.05, y: view.center.y-view.frame.height * 0.05, width: view.frame.width * 0.1, height: view.frame.height * 0.1)
// start with viewDrag
// width = "slidermultiplier" percent of view width
widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
// Leading = "tim" pts from view leading
viewDragLeadingConstraint = viewDrag.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: tim)
// centered vertically
viewDragCenterYConstraint = viewDrag.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([
// viewDrag height will never change, so we can set it here
viewDrag.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
// activate the 3 "modifiable" constraints
widthConstraints,
viewDragLeadingConstraint,
viewDragCenterYConstraint,
])
panGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedView(_:)))
viewDrag.isUserInteractionEnabled = true
viewDrag.addGestureRecognizer(panGesture)
// start the slider at the same percentage we've used
// for viewDrag's initial width
slizer.value = Float(slidermultiplier)
}
@objc func draggedView(_ sender: UIPanGestureRecognizer) {
// old swift syntax
//self.view.bringSubview(toFront: viewDrag)
self.view.bringSubviewToFront(viewDrag)
let translation = sender.translation(in: self.view)
viewDragLeadingConstraint.constant += translation.x
viewDragCenterYConstraint.constant += translation.y
// don't do this
//viewDrag.center = CGPoint(x: viewDrag.center.x + translation.x , y: viewDrag.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: self.view)
}
@objc func increase() {
// get the new value of the slider
slidermultiplier = CGFloat(slizer.value)
// deactivate widthConstraints
widthConstraints.isActive = false
// create new widthConstraints with slider value as a multiplier
widthConstraints = viewDrag.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
// activate the new widthConstraints
widthConstraints.isActive = true
}
}
推荐阅读
- java - 如何从 Web 中提取 Microsoft Power BI 数据
- database - 为什么 SERM (ERM) 建模中关系类型的主键 (PK) 需要继承类型?
- python - pytest - 模拟配置[
] 通过 configparser.ConfigParser() / config.read() - mysql - 为什么 NOT NULL DEFAULT current_timestamp() 在创建此表时会给出错误 Invalid default value?
- api - 如何在 laravel 8 api 中使用外键获取、插入和更新数据
- c# - 比较一系列两个变量的最简洁方法?
- javascript - Object.defineProperty 不更改键顺序
- c# - 在 .NET 5 中,有没有办法提前将代码编译成二进制文件并仅剥离 IL(而不是反射数据)?
- javascript - Javascript:如何通过触摸选择文本并防止拖动屏幕
- javascript - 按最新的优先顺序订购 Firestore 文档