取消激活将它们链接在一起的 2 个对象之间的约束
De activate constraints between 2 objects linking them together
我的 swift 代码,您可以在下面的 gif 中看到。让用户 select 图像视图之一,然后使用滑块增加或减小该图像视图的大小。问题是当图像视图移动时,另一个图像视图跟随它,这是不应该发生的。因此,应该在代码第一次运行时但在其中一个图像视图 selected 之后设置约束。将它们链接在一起的约束应该被停用。导致这个的一行是
** greenMove.leadingAnchor.constraint(等于:view.leadingAnchor,常量:0),**
import UIKit
class ViewController: UIViewController {
var image1Width: NSLayoutConstraint!
var image1Height: NSLayoutConstraint!
var image1Width2: NSLayoutConstraint!
var image1Height2: NSLayoutConstraint!
var greenMove = UIImageView()
var slider = UISlider()
var blueMove = UIImageView()
var existingTransition : CGAffineTransform?
var clock = Int()
var currentView: UIView?
var g2 = UIPanGestureRecognizer()
var g3 = UIPanGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
greenMove.isUserInteractionEnabled = true
blueMove.isUserInteractionEnabled = true
g2 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))
greenMove.addGestureRecognizer(g2)
g3 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g2Method))
blueMove.addGestureRecognizer(g3)
greenMove.backgroundColor = .systemGreen
blueMove.backgroundColor = .blue
[greenMove,slider,blueMove].forEach {
view.addSubview([=10=])
[=10=].translatesAutoresizingMaskIntoConstraints = false
}
//image11
image1Width = greenMove.widthAnchor.constraint(equalTo: view.widthAnchor ,multiplier: 0.2)
image1Height = greenMove.heightAnchor.constraint(equalTo: view.heightAnchor ,multiplier: 0.20)
//image12
image1Width2 = blueMove.widthAnchor.constraint(equalTo: view.widthAnchor ,multiplier: 0.2)
image1Height2 = blueMove.heightAnchor.constraint(equalTo: view.heightAnchor ,multiplier: 0.20)
NSLayoutConstraint.activate([
greenMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
image1Width,
image1Height,
greenMove.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant :0),
blueMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
image1Width2,
image1Height2,
blueMove.leadingAnchor.constraint(equalTo: greenMove.trailingAnchor, constant :0)
])
slider.addTarget(self, action: #selector(hhh), for: .allEvents)
}
override func viewDidLayoutSubviews() {
NSLayoutConstraint.activate ([
slider.topAnchor.constraint(equalTo: view.topAnchor, constant : greenMove.bounds.height),
slider.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.20, constant: 0),
slider.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.20, constant: 0),
slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),
])
}
@objc func handleTapGestured(_ gesture: UIPanGestureRecognizer) {
currentView = gesture.view
}
@objc func g1Method(_ sender: UIPanGestureRecognizer){
clock = 1
let subview = greenMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
switch sender.state {
case .ended,.cancelled:// on End
if let existing = existingTransition{
self.existingTransition = newTransition.concatenating(existing)
}else{
self.existingTransition = newTransition
}
default://on change and other states
if let existing = existingTransition{
child.transform = newTransition
.concatenating(existing)
}else{
child.transform = newTransition
}
}
self.view.layoutIfNeeded()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
subview.addGestureRecognizer(tapGesture)
}
@objc func g2Method(_ sender: UIPanGestureRecognizer){
clock = 2
let subview = blueMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
switch sender.state {
case .ended,.cancelled:// on End
if let existing = existingTransition{
self.existingTransition = newTransition.concatenating(existing)
}else{
self.existingTransition = newTransition
}
default://on change and other states
if let existing = existingTransition{
child.transform = newTransition
.concatenating(existing)
}else{
child.transform = newTransition
}
}
self.view.layoutIfNeeded()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
subview.addGestureRecognizer(tapGesture)
}
@objc func hhh() {
if clock == 1 {
image1Width.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
image1Height.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
}
if clock == 2 {
image1Width2.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
image1Height2.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
}
}
}
最好的方法是在安全区域前导和图像前导之间创建蓝图前导约束,而不是在两个图像之间创建前导约束,因为当您禁用两个图像之间的约束时,您会遇到错误,因为视图没有'不知道把图片放在哪里
您 运行 遇到的问题是因为您对两个视图都使用了一个变换,并连接了新的变换信息,当您尝试移动它时,该信息将应用于另一个视图。
对您发布的代码进行这些更改...
在 class 级别,创建单独的转换 "trackers":
// don't use this
//var existingTransition : CGAffineTransform?
// separate transforms for each "move view"
var blueTransition: CGAffineTransform?
var greenTransition: CGAffineTransform?
然后,在 g1Method
和 g2Method
中使用关联的转换:
@objc func g1Method(_ sender: UIPanGestureRecognizer){
clock = 1
let subview = greenMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
// greenMove view must track its own CGAffineTransform
switch sender.state {
case .ended,.cancelled:// on End
if let existing = greenTransition {
greenTransition = newTransition.concatenating(existing)
} else {
greenTransition = newTransition
}
//if let existing = existingTransition{
// self.existingTransition = newTransition.concatenating(existing)
//}else{
// self.existingTransition = newTransition
//}
default://on change and other states
if let existing = greenTransition {
child.transform = newTransition
.concatenating(existing)
} else {
child.transform = newTransition
}
//if let existing = existingTransition{
// child.transform = newTransition
// .concatenating(existing)
//}else{
// child.transform = newTransition
//}
}
self.view.layoutIfNeeded()
// move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
//let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
//subview.addGestureRecognizer(tapGesture)
}
@objc func g2Method(_ sender: UIPanGestureRecognizer){
clock = 2
let subview = blueMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
// blueMove view must track its own CGAffineTransform
switch sender.state {
case .ended,.cancelled:// on End
if let existing = blueTransition {
blueTransition = newTransition.concatenating(existing)
} else {
blueTransition = newTransition
}
//if let existing = existingTransition{
// self.existingTransition = newTransition.concatenating(existing)
//}else{
// self.existingTransition = newTransition
//}
default://on change and other states
if let existing = blueTransition {
child.transform = newTransition
.concatenating(existing)
} else {
child.transform = newTransition
}
//if let existing = existingTransition{
// child.transform = newTransition
// .concatenating(existing)
//}else{
// child.transform = newTransition
//}
}
self.view.layoutIfNeeded()
// move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
//let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
//subview.addGestureRecognizer(tapGesture)
}
我的 swift 代码,您可以在下面的 gif 中看到。让用户 select 图像视图之一,然后使用滑块增加或减小该图像视图的大小。问题是当图像视图移动时,另一个图像视图跟随它,这是不应该发生的。因此,应该在代码第一次运行时但在其中一个图像视图 selected 之后设置约束。将它们链接在一起的约束应该被停用。导致这个的一行是
** greenMove.leadingAnchor.constraint(等于:view.leadingAnchor,常量:0),**
import UIKit
class ViewController: UIViewController {
var image1Width: NSLayoutConstraint!
var image1Height: NSLayoutConstraint!
var image1Width2: NSLayoutConstraint!
var image1Height2: NSLayoutConstraint!
var greenMove = UIImageView()
var slider = UISlider()
var blueMove = UIImageView()
var existingTransition : CGAffineTransform?
var clock = Int()
var currentView: UIView?
var g2 = UIPanGestureRecognizer()
var g3 = UIPanGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
greenMove.isUserInteractionEnabled = true
blueMove.isUserInteractionEnabled = true
g2 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))
greenMove.addGestureRecognizer(g2)
g3 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g2Method))
blueMove.addGestureRecognizer(g3)
greenMove.backgroundColor = .systemGreen
blueMove.backgroundColor = .blue
[greenMove,slider,blueMove].forEach {
view.addSubview([=10=])
[=10=].translatesAutoresizingMaskIntoConstraints = false
}
//image11
image1Width = greenMove.widthAnchor.constraint(equalTo: view.widthAnchor ,multiplier: 0.2)
image1Height = greenMove.heightAnchor.constraint(equalTo: view.heightAnchor ,multiplier: 0.20)
//image12
image1Width2 = blueMove.widthAnchor.constraint(equalTo: view.widthAnchor ,multiplier: 0.2)
image1Height2 = blueMove.heightAnchor.constraint(equalTo: view.heightAnchor ,multiplier: 0.20)
NSLayoutConstraint.activate([
greenMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
image1Width,
image1Height,
greenMove.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant :0),
blueMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
image1Width2,
image1Height2,
blueMove.leadingAnchor.constraint(equalTo: greenMove.trailingAnchor, constant :0)
])
slider.addTarget(self, action: #selector(hhh), for: .allEvents)
}
override func viewDidLayoutSubviews() {
NSLayoutConstraint.activate ([
slider.topAnchor.constraint(equalTo: view.topAnchor, constant : greenMove.bounds.height),
slider.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.20, constant: 0),
slider.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.20, constant: 0),
slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),
])
}
@objc func handleTapGestured(_ gesture: UIPanGestureRecognizer) {
currentView = gesture.view
}
@objc func g1Method(_ sender: UIPanGestureRecognizer){
clock = 1
let subview = greenMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
switch sender.state {
case .ended,.cancelled:// on End
if let existing = existingTransition{
self.existingTransition = newTransition.concatenating(existing)
}else{
self.existingTransition = newTransition
}
default://on change and other states
if let existing = existingTransition{
child.transform = newTransition
.concatenating(existing)
}else{
child.transform = newTransition
}
}
self.view.layoutIfNeeded()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
subview.addGestureRecognizer(tapGesture)
}
@objc func g2Method(_ sender: UIPanGestureRecognizer){
clock = 2
let subview = blueMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
switch sender.state {
case .ended,.cancelled:// on End
if let existing = existingTransition{
self.existingTransition = newTransition.concatenating(existing)
}else{
self.existingTransition = newTransition
}
default://on change and other states
if let existing = existingTransition{
child.transform = newTransition
.concatenating(existing)
}else{
child.transform = newTransition
}
}
self.view.layoutIfNeeded()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
subview.addGestureRecognizer(tapGesture)
}
@objc func hhh() {
if clock == 1 {
image1Width.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
image1Height.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
}
if clock == 2 {
image1Width2.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
image1Height2.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
}
}
}
最好的方法是在安全区域前导和图像前导之间创建蓝图前导约束,而不是在两个图像之间创建前导约束,因为当您禁用两个图像之间的约束时,您会遇到错误,因为视图没有'不知道把图片放在哪里
您 运行 遇到的问题是因为您对两个视图都使用了一个变换,并连接了新的变换信息,当您尝试移动它时,该信息将应用于另一个视图。
对您发布的代码进行这些更改...
在 class 级别,创建单独的转换 "trackers":
// don't use this
//var existingTransition : CGAffineTransform?
// separate transforms for each "move view"
var blueTransition: CGAffineTransform?
var greenTransition: CGAffineTransform?
然后,在 g1Method
和 g2Method
中使用关联的转换:
@objc func g1Method(_ sender: UIPanGestureRecognizer){
clock = 1
let subview = greenMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
// greenMove view must track its own CGAffineTransform
switch sender.state {
case .ended,.cancelled:// on End
if let existing = greenTransition {
greenTransition = newTransition.concatenating(existing)
} else {
greenTransition = newTransition
}
//if let existing = existingTransition{
// self.existingTransition = newTransition.concatenating(existing)
//}else{
// self.existingTransition = newTransition
//}
default://on change and other states
if let existing = greenTransition {
child.transform = newTransition
.concatenating(existing)
} else {
child.transform = newTransition
}
//if let existing = existingTransition{
// child.transform = newTransition
// .concatenating(existing)
//}else{
// child.transform = newTransition
//}
}
self.view.layoutIfNeeded()
// move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
//let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
//subview.addGestureRecognizer(tapGesture)
}
@objc func g2Method(_ sender: UIPanGestureRecognizer){
clock = 2
let subview = blueMove
guard let child = sender.view else{return}
let transitionPoint = sender.translation(in: self.view)
let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
// blueMove view must track its own CGAffineTransform
switch sender.state {
case .ended,.cancelled:// on End
if let existing = blueTransition {
blueTransition = newTransition.concatenating(existing)
} else {
blueTransition = newTransition
}
//if let existing = existingTransition{
// self.existingTransition = newTransition.concatenating(existing)
//}else{
// self.existingTransition = newTransition
//}
default://on change and other states
if let existing = blueTransition {
child.transform = newTransition
.concatenating(existing)
} else {
child.transform = newTransition
}
//if let existing = existingTransition{
// child.transform = newTransition
// .concatenating(existing)
//}else{
// child.transform = newTransition
//}
}
self.view.layoutIfNeeded()
// move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
//let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
//subview.addGestureRecognizer(tapGesture)
}