无法使用 UIimageView 激活带有锚点错误的约束
Unable to activate constraint with anchors error with UIimageView
第一次在这里发帖。
所以我一直在尝试制作一个 UIimageView 的动画。到目前为止,我是这样做的。所以图像从屏幕中间移动到顶部。我希望能够制作带有约束的动画。但是在尝试添加一些约束时,我收到此错误“无法使用锚点错误激活约束”。
这是我尝试向 banditLogo imageview 添加一些约束的代码。
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(banditLogo)
view.translatesAutoresizingMaskIntoConstraints = false // autolayout activation
chooseLabel.alpha = 0
signInButtonOutlet.alpha = 0
self.banditLogo.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 304).isActive = true
self.banditLogo.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 94).isActive = true
self.banditLogo.widthAnchor.constraint(equalToConstant: 224).isActive = true
self.banditLogo.heightAnchor.constraint(equalToConstant: 289).isActive = true
}
这里是制作动画的函数。
此函数在 viewDidAppear 中被调用,函数的 animatedImage 变量被引用到 banditLogo UIimageView。
所以当视图屏幕加载时,图像移动到视图的顶部。
func logoAnimate(animatedImage: UIImageView!, animatedLabel: UILabel!) {
UIView.animate(withDuration: 1.5, delay: 1, options: [.allowAnimatedContent]) {
animatedImage.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 5).isActive = true
animatedImage.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor, constant: 94).isActive = true
} completion: { (true) in
UIView.animate(withDuration: 0.25) {
animatedLabel.alpha = 1
}
}
}
我通过 更改 约束而不是 设置 来为具有约束的视图设置动画。保留静态约束“原样”——即使用 isActive = true
。但是那些你想改变的?将它们放在 两个 数组和 activate/deactivte 中。使用 UIView.animate
.
像您一样完成动画
例如,假设您希望将 banditLogo
从前 304 位移动到前 5 位,这在我看来就是您想要做的。将 all 其他约束保持原样 - 左侧(您的代码似乎没有更改)、高度和宽度。现在,创建两个数组:
var start = [NSLayoutConstraint]()
var finish = [NSLayoutConstraint]()
添加变化的约束。请注意,我没有将它们设置为活动状态:
start.append(banditLogo.topAnchor.constraint(equalTo: safeAreaView.topAnchor, constant: 305))
finish.append(banditLogo.topAnchor.constraint(equalTo: safeAreaView.topAnchor, constant: 5))
根据需要在 viewDidLoad
或任何其他视图控制器方法中初始化:
NSLayoutConstraint.activate(start)
最后,当您想要制作动画时,deactivate/activate 并告诉视图显示动画:
NSLayoutConstraint.deactivate(start)
NSLayoutConstraint.activate(finish)
UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() }
最后一篇评论,无意冒犯。
我觉得你发布的代码中有些东西很乱。创建一个移动单个视图的函数应该直接处理视图恕我直言,而不是将视图传递给它。也许您正在尝试以这种方式移动多个视图 - 在这种情况下这是很好的代码 - 但您的问题中没有任何暗示。可以在函数中执行动画 - 这样您就可以在需要时调用它。我一直这样做是为了这样的事情 - 将工具覆盖层滑入和滑出。但是,如果您对单个视图执行此操作,只需直接解决它。代码对其他编码人员更易读。
此外,我对 start
的偏好在 viewDidLoad
中,除非 VC 是导航堆栈的一部分。但在那种情况下,不要只是使用viewDidAppear
,在viewDidDisappear
.
中设置回start
编辑:查看评论,我假设是你已经在每个需要的视图上正确使用translatesAutoresizingMaskIntoConstraints = false
.
您可能会发现创建一个 class 级 属性 来保存图像视图的顶部约束,然后在您想要移动它时更改该约束的 .constant
值会更容易。
这是一个简单的示例 - 点击视图上的任意位置将使图像视图上下移动:
class AnimLogoViewController: UIViewController {
let banditLogo = UIImageView()
// we'll change this constraint's .constant to change the image view's position
var logoTopConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
if let img = UIImage(systemName: "person.fill") {
banditLogo.image = img
}
view.addSubview(banditLogo)
// I assume this was a typo... you want to set it on the image view, not the controller's view
//view.translatesAutoresizingMaskIntoConstraints = false // autolayout activation
banditLogo.translatesAutoresizingMaskIntoConstraints = false // autolayout activation
// create the image view's top constraint
logoTopConstraint = banditLogo.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 304)
// activate it
logoTopConstraint.isActive = true
// non-changing constraints
self.banditLogo.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 94).isActive = true
self.banditLogo.widthAnchor.constraint(equalToConstant: 224).isActive = true
self.banditLogo.heightAnchor.constraint(equalToConstant: 289).isActive = true
// animate the logo when you tap the view
let t = UITapGestureRecognizer(target: self, action: #selector(self.didTap(_:)))
view.addGestureRecognizer(t)
}
@objc func didTap(_ g: UITapGestureRecognizer) -> Void {
// if the logo image view is at the top, animate it down
// else, animate it up
if logoTopConstraint.constant == 5.0 {
logoTopConstraint.constant = 304.0
} else {
logoTopConstraint.constant = 5.0
}
UIView.animate(withDuration: 1.5, animations: {
self.view.layoutIfNeeded()
})
}
}
第一次在这里发帖。
所以我一直在尝试制作一个 UIimageView 的动画。到目前为止,我是这样做的。所以图像从屏幕中间移动到顶部。我希望能够制作带有约束的动画。但是在尝试添加一些约束时,我收到此错误“无法使用锚点错误激活约束”。
这是我尝试向 banditLogo imageview 添加一些约束的代码。
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(banditLogo)
view.translatesAutoresizingMaskIntoConstraints = false // autolayout activation
chooseLabel.alpha = 0
signInButtonOutlet.alpha = 0
self.banditLogo.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 304).isActive = true
self.banditLogo.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 94).isActive = true
self.banditLogo.widthAnchor.constraint(equalToConstant: 224).isActive = true
self.banditLogo.heightAnchor.constraint(equalToConstant: 289).isActive = true
}
这里是制作动画的函数。
此函数在 viewDidAppear 中被调用,函数的 animatedImage 变量被引用到 banditLogo UIimageView。 所以当视图屏幕加载时,图像移动到视图的顶部。
func logoAnimate(animatedImage: UIImageView!, animatedLabel: UILabel!) {
UIView.animate(withDuration: 1.5, delay: 1, options: [.allowAnimatedContent]) {
animatedImage.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 5).isActive = true
animatedImage.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor, constant: 94).isActive = true
} completion: { (true) in
UIView.animate(withDuration: 0.25) {
animatedLabel.alpha = 1
}
}
}
我通过 更改 约束而不是 设置 来为具有约束的视图设置动画。保留静态约束“原样”——即使用 isActive = true
。但是那些你想改变的?将它们放在 两个 数组和 activate/deactivte 中。使用 UIView.animate
.
例如,假设您希望将 banditLogo
从前 304 位移动到前 5 位,这在我看来就是您想要做的。将 all 其他约束保持原样 - 左侧(您的代码似乎没有更改)、高度和宽度。现在,创建两个数组:
var start = [NSLayoutConstraint]()
var finish = [NSLayoutConstraint]()
添加变化的约束。请注意,我没有将它们设置为活动状态:
start.append(banditLogo.topAnchor.constraint(equalTo: safeAreaView.topAnchor, constant: 305))
finish.append(banditLogo.topAnchor.constraint(equalTo: safeAreaView.topAnchor, constant: 5))
根据需要在 viewDidLoad
或任何其他视图控制器方法中初始化:
NSLayoutConstraint.activate(start)
最后,当您想要制作动画时,deactivate/activate 并告诉视图显示动画:
NSLayoutConstraint.deactivate(start)
NSLayoutConstraint.activate(finish)
UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() }
最后一篇评论,无意冒犯。
我觉得你发布的代码中有些东西很乱。创建一个移动单个视图的函数应该直接处理视图恕我直言,而不是将视图传递给它。也许您正在尝试以这种方式移动多个视图 - 在这种情况下这是很好的代码 - 但您的问题中没有任何暗示。可以在函数中执行动画 - 这样您就可以在需要时调用它。我一直这样做是为了这样的事情 - 将工具覆盖层滑入和滑出。但是,如果您对单个视图执行此操作,只需直接解决它。代码对其他编码人员更易读。
此外,我对 start
的偏好在 viewDidLoad
中,除非 VC 是导航堆栈的一部分。但在那种情况下,不要只是使用viewDidAppear
,在viewDidDisappear
.
start
编辑:查看评论,我假设是你已经在每个需要的视图上正确使用translatesAutoresizingMaskIntoConstraints = false
.
您可能会发现创建一个 class 级 属性 来保存图像视图的顶部约束,然后在您想要移动它时更改该约束的 .constant
值会更容易。
这是一个简单的示例 - 点击视图上的任意位置将使图像视图上下移动:
class AnimLogoViewController: UIViewController {
let banditLogo = UIImageView()
// we'll change this constraint's .constant to change the image view's position
var logoTopConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
if let img = UIImage(systemName: "person.fill") {
banditLogo.image = img
}
view.addSubview(banditLogo)
// I assume this was a typo... you want to set it on the image view, not the controller's view
//view.translatesAutoresizingMaskIntoConstraints = false // autolayout activation
banditLogo.translatesAutoresizingMaskIntoConstraints = false // autolayout activation
// create the image view's top constraint
logoTopConstraint = banditLogo.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 304)
// activate it
logoTopConstraint.isActive = true
// non-changing constraints
self.banditLogo.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 94).isActive = true
self.banditLogo.widthAnchor.constraint(equalToConstant: 224).isActive = true
self.banditLogo.heightAnchor.constraint(equalToConstant: 289).isActive = true
// animate the logo when you tap the view
let t = UITapGestureRecognizer(target: self, action: #selector(self.didTap(_:)))
view.addGestureRecognizer(t)
}
@objc func didTap(_ g: UITapGestureRecognizer) -> Void {
// if the logo image view is at the top, animate it down
// else, animate it up
if logoTopConstraint.constant == 5.0 {
logoTopConstraint.constant = 304.0
} else {
logoTopConstraint.constant = 5.0
}
UIView.animate(withDuration: 1.5, animations: {
self.view.layoutIfNeeded()
})
}
}