Here is an image of a simple APP I am trying to make
App有一个用于中心紫色按钮的平移手势识别器,如果它与4个橙色按钮中的任何一个相交,则移动按钮,紫色按钮动画并在其相交的按钮边界内移动,否则它会动画回到初始起始位置即中心。
第一次当我平移紫色按钮时,按钮的框架会更新,但是如果我第二次尝试按钮的框架保持不变(当它在视图中心时的值) )。
我猜这是与我错过的自动布局有关的东西,因为如果我删除中心紫色按钮上的约束,如果我平移,框架每次都会正确更新。
任何人都可以解释在使用约束设置动画时我必须记住的内容
这是我处理Pan手势的代码:
@objc func handleCenterRectPan(_ pannedView: UIPanGestureRecognizer) {
let fallBackAnimation = UIViewPropertyAnimator(duration: 0.3, dampingRatio: 0.5) {
if self.button1.frame.intersects(self.centerRect.frame) {
self.centerRect.center = self.button1.center
} else if self.button2.frame.contains(self.centerRect.frame) {
self.centerRect.center = self.button2.center
} else if self.button3.frame.contains(self.centerRect.frame) {
self.centerRect.center = self.button3.center
} else if self.button4.frame.contains(self.centerRect.frame) {
self.centerRect.center = self.button4.center
} else {
// no intersection move to original position
self.centerRect.frame = OGValues.oGCenter
}
}
switch pannedView.state {
case .began:
self.centerRect.center = pannedView.location(in: self.view)
case .changed:
print("Changed")
self.centerRect.center = pannedView.location(in: self.view)
case .ended, .cancelled, .failed :
print("Ended")
fallBackAnimation.startAnimation();
//snapTheRectangle()
default:
break
}
}
答案 0 :(得分:0)
首先,如果您的目标是顺利移动您的观点,则不应该给予限制。如果你无法抵抗约束,你必须不断更新约束而不是帧(中心), 在您的代码中,我假设您已经给出了紫色按钮中心约束,然后您在使用平移手势进行用户拖动时更改按钮的中心。问题是您给出的约束仍处于活动状态,并且一旦布局需要更新,它就会尝试将其设置回来。
所以你可以做的是
不要给出约束,因为当用户拖动时需要自由移动
OR
为约束创建IBoutlet,并在用户拖动时将.isActive设置为false,如果它不在任何其他按钮内并且更新UpdateLayoutIfNeeded,则将其设置为true,这样它将返回到原始位置。 (好方法)
@IBOutlet var horizontalConstraints: NSLayoutConstraint!
@IBOutlet var verticalConstraints: NSLayoutConstraint!
//make active false as the user is dragging the view
horizontalConstraints.isActive = false
verticalConstraints.isActive = false
self.view.layoutIfNeeded()
//make it true again if its not inside any of the other views
horizontalConstraints.isActive = true
verticalConstraints.isActive = true
self.view.layoutIfNeeded()
OR
当用户移动视图时更新水平和垂直约束的constraints.constants(不是一个好方法),如果它不在任何其他视图中,则再次将其设为零
//make it true again if its not inside any of the other views
horizontalConstraints.constant = change in horizontal direction
verticalConstraints..constant = change in vertical direction
self.view.layoutIfNeeded()
编辑正如您所说,设置isActive = false后约束为零,因为 实际做的是添加和删除这些约束,如Apple doc所说
激活或取消激活约束会在视图上调用addConstraint( :)和removeConstraint( :),该视图是此约束管理的项目的最近共同祖先。使用此属性而不是直接调用addConstraint( :)或removeConstraint( :)。
因此,制定约束强引用确实可以解决问题,但我认为设置对IBOutelet的强引用并不是一个好主意,以编程方式添加和删除约束更好。看看这个问题解除分配约束