Is it possible to make a UIView animation by changing constraints?
Basically, I want to animate myv (UIView) which has x, y, height and width constraints, using: UIView.animateWithDuration(1.5) {} by changing the old constraints.
Yes this is possible. You can do something like this:
func AnimateHeight() {
UIView.animateWithDuration(1.5, animations: {
self.heightCons.constant = 250 // Some value
self.view.layoutIfNeeded()
})
}
Where self.heightCons is an IBOutlet to the height constraint on the UIView.
If you don't use storyboards you can check out how to create layout constraints programmatically.
For info on Core Animation and Auto layout: Combining autolayout with core animation
Related
I'm trying to animate constraints in my ViewController.
In order to do that, I added this line to my code:
I'm just trying to change the height of a UIView() (from 0 to 100)
barHeight.constant = CGFloat(100)
UIView.animate(withDuration: 2) {self.view.layoutIfNeeded()}
The problem is that, with that line, all of the constraints are animated, and it's not what I would like.
Do you know how I could animate only specific constraints and not others?
Call layoutSubviews before you edit the constraint you want to animate. This will cause any pending layout updates to be applied without any animation and then you can change the next constraint with animation.
Like so:
self.view.layoutSubviews()
barHeight.constant = CGFloat(100)
UIView.animate(withDuration: 2) {self.view.layoutIfNeeded()}
I am making a card app and I need to make an animation so that a card would change its constraints to move to another place. How would I do this for a UIImage.
Hook the leading , trailing , CenterX OR CenterY constraint of the UIImageView and do this
self.imageLeadCon.constant = // value
UIView.animate(withDuration: 3.0 , animations: {
self.view.layoutIfNeeded()
// animation
}, completion: { _ in
// completion
})
I think you're confusing UIImage with UIImageView. The first one is the image's data representation, the second one is the View that displays the UIImage.
So I guess you want to move around the UIImageView. To do that obtain a reference to the constraints (e.g. by ctrl-dragging from the constraint in the storyboard to your UIViewController instance).
After that you can update the constraint in an animation block like here:
// Make sure the view is laid out as Mischanya Schtrigel stated
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.5) { // duration in seconds
myConstraint.constant = 50 // update your constraint here
self.view.layoutIfNeeded()
}
Contrary to the other answers, I like putting the constraint changes in the animation closure to make it more clear what is going to be animated.
First of all you have to drag and drop your constraint into your view controller, to make an outlet. The same way you are doing it with UIImageView or UITableView, etc.
Actually, for those who have watched WWDC (2014 I guess), Apple have explained how to animate UI in the proper way.
Firstly, you have to call layoutIfNeeded() method to make sure that everything on your view have laid out. After you can change your constraint and right after that in your animation block you call layoutIfNeeded() method to layout your constraint with the new value.
So code should look like that:
view.layoutIfNeeded() // to make sure your view have laid out
self.constraint.constant = //change your constant to any value
UIView.animate(withDuration: 1.0) {
self.view.layoutIfNeeded() //layout your constraint with the new value
}
I have a UIView, that contains a UILabel (and nothing else) inside it. I wish to expand and contract the view, making it look as though the label is expanding and contracting (via a button tap). I'm using a NSLayoutConstraint on the height of the view:
func labelExpansion() {
if (isExpanded) {
myViewConstraint.constant = shortLabelHeight
} else {
myViewConstraint.constant = longLabelHeight
}
UIView.animate(withDuration: 2.2, animations: {
self.view.layoutIfNeeded()
})
}
The problem is, the text in the label looks like it 'jumps'. As the label is resizing, the position of the text changes, until the animation is finished, when the label correctly redraws to the top of the view.
I have also tried removing the surrounding view, and adjusting the height constraint of the label alone; that was similarly jumpy.
How can I stop this jump during the animation, and fix the top of the label to the top of the view?
After trying a few things, I found an easy solution: set the Content Mode of the UILabel to 'Top'.
myLabel.contentMode = .top
I have created a storyboard as in the image. In that I have set the vertical spacing between the red view and tableView is around 20. Its working good.
But when i tried to change the height of red view then the tableview should comes up with the constraints I added but the table view is remained constant at the same place.
I used the following code
redView.frame.size = CGSize(width: 1008, height: 0)
self.view.layoutIfNeeded()
Whenever you are adding a constraint to any object on storyboard then onwards that object's frame will be maintained by autolayout engine. This is the primary design principle I guess. In this case what you can simply do is that just make an outlet of the desired constraint which you want to update and update that constraint within your code. For your understanding I am attaching a screenshot.
Now after making a constraint outlet it must look like as follows.
#IBOutlet weak var containerViewHeight: NSLayoutConstraint!
Now to update the height you just have to do one thing.
containerViewHeight.constant = 0
In my opinion if this update is not working inside viewDidLoad or viewWillAppear then please update inside viewDidLayoutSubviews because when viewDidLoad get called then iOS doesn't apply the layout properly.
In my case what I will do is -
override func viewDidLayoutSubviews() { //This ensures all the layout has been applied properly.
super.viewDidLayoutSubviews()
containerViewHeight.constant = 0
}
Note: - To achieve some nice animation effect during layout changes you can apply this constraint update inside an UIView animation block like as follows. But remember, to see the effect nicely you have to call this after presenting the view properly like after viewDidAppear etc.
UIView.animateWithDuration(1.0, delay: 0.2, usingSpringWithDamping: 8.0, initialSpringVelocity: 1.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
containerViewHeight.constant = 0
self.view.layoutIfNeeded()
}, completion: nil)
Sorry for any mistake.
Update/Edit is most welcome.
Hope this helped. Thanks
You should be using Autolayout to manipulate the redView's height. Modifying its frame's size is not Autolayout. Modify its height constraint (if it exists)
You need to either use constraints or changes to frames! You cannot do both!
What you need to do is to make an outlet reference to your constraint and change its constant-value instead.
If you placed the code in viewdidload or viewwillappear, you will find issues like this. You need to put the code after all the constraints are loaded.
Also, make an object of the height constraint and name it for example redViewHeight.
and change its value by: redViewHeight.constant = 0
It will work!
Replace the constraints for the views with the following.
Redview
Top constraint to ParentView
Leading Constraint to ParentView
Trailing constraint to ParentView
Height Constraint
TableView
Top constraint to RedView
Leading Constraint to ParentView
Trailing constraint to ParentView
Bottom constraint to ParentView
Now wire an IBOutlet for the HeightConstraint of RedView and modify its constant value. The UITableView will adjust its height as desired.
I have UITableView as a subview over UIView (parent view) of UIViewController. When i'm animating my parent view as below:
UIView.animateWithDuration(duration, animations: {
viewController?.view.frame = CGRectMake(0,0,320,568)
}, completion: {_ in
})
I observed that my subview (table view) is not animating. I tried setting Autoresizing Mask of subviews to flexibleWidth and flexibleHeight, but din't get any success. Anybody having any idea why its happening.
If you are using auto layout (which is the default in iOS 8/9 on Xcode 6/7) you need to change the constraints of your view inside he UIView animation closure, instead of changing the frame.
If you are not using auto layout, then you can update the frame as above, however, I'd imagine you are. Thus you need to call layoutSubviews, then programatically set new constraints that represent your desired change to the layout, and finally call layoutSubviews again, inside the animation closure.
Example:
func AnimateBackgroundHeight() {
self.view.layoutSubviews()
UIView.animateWithDuration(0.5, animations: {
self.heightCon.constant = 600 // heightCon is the IBOutlet to the constraint
self.view.layoutSubviews()
})
}