Posting a question for the first time here.
So I have been trying to make an animation of an UIimageView. I did that so far. So the image moves from the middle of the screen to the top. I want to be able to make that animation with constraints. But while trying to add some constraints, I receive this error "Unable to activate constraint with anchors error".
here is the code which I try to add some constraints to 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
}
and here is the func that makes the animation.
this func is being called in viewDidAppear and animatedImage variable of the function is referred to banditLogo UIimageView.
so when the view screen loads up, the image moves to top of the view.
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
}
}
}
2
Answers
I animate views that have constraints by changing constraints, not setting them. Leave the constraints that are static "as is" – that is, use
isActive = true
. But those you wish to change? Put them in two arrays and activate/deactivte them. Complete the animation like you are by usingUIView.animate
.For instance, let’s say you wish to move
banditLogo
from top 304 to top 5, which appears to me to be what you trying to do. Leave all other constraints as is – left (which your code doesn’t seem to change), height, and width. Now, create two arrays:Add in the constraints that change. Note that I’m not setting them as active:
Initialize things in
viewDidLoad
or any other view controller method as needed:Finally, when you wish to do the animation, deactivate/activate and tell the view to show the animation:
Last piece of critique, made with no intent of being offending.
Something in your code posted feels messy to me. Creating a function to move a single view should directly address the view IMHO, not pass the view into it. Maybe you are trying to move several views this way – in which case this is good code – but nothing in your question suggests it. It’s okay to do the animation in a function – that way you can call it when needed. I do this all the time for something like this – sliding a tool overlay in and out. But if you are doing this to a single view, just address it directly. The code is more readable to other coders.
Also, my preference for the
start
is inviewDidLoad
unless the VC is part of a navigation stack. But in that case, don’t just useviewDidAppear
, set things back tostart
inviewDidDisappear
.EDIT: looking at the comments, I assumed that yes you have already used
translatesAutoresizingMaskIntoConstraints = false
properly on every view needed.You may find it easier to create a class-level property to hold the image view’s top constraint, then change that constraint’s
.constant
value when you want to move it.Here’s a quick example – tapping anywhere on the view will animate the image view up or down: