How do I animate a NSLayoutConstraint in Swift?
By the time you hit viewDidLoad
, the constraints engine has not yet been applied and the starting location of the views has not yet been established. So, feel free to add the original constraints in viewDidLoad
, but you will want to defer the animateWithDuration
until later in the process (e.g. viewDidAppear
).
For example, let's assume you have some constraint that you added in Interface Builder (IB). You can add an@IBOutlet
reference to it by control-dragging from the constraint in the document outline in the left panel in Interface Builder down to the assistant editor:
Now that you have a reference to that constraint, you can now programmatically alter the constant
value for that constraint (but, again, do this in viewDidAppear
, not viewDidLoad
, if you want to see this animated when the view is presented):
@IBOutlet weak var topConstraint: NSLayoutConstraint!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
topConstraint.constant = 100
UIView.animate(withDuration: 2) {
self.view.layoutIfNeeded()
}
}
The process is the same for programmatically created constraints. Just save a reference to the constraint and then in viewDidAppear
update the constant
and then animate the call to layoutIfNeeded()
.
trying to animate a constraint in swift
You need to first change the constraint and then animate the update.
This should be in the superview.
self.nameInputConstraint.constant = 8
Swift 2
UIView.animateWithDuration(0.5) {
self.view.layoutIfNeeded()
}
Swift 3, 4, 5
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
Simple slide up animation on UIView using NSLayoutConstraints
good day I usually work with transform property for move one view from x position to y portion, please check this example.
class ViewController: UIViewController {
let button : UIButton = {
let button = UIButton(type: .custom)
button.setTitle("Button", for: .normal)
button.backgroundColor = .gray
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let customView : UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .red
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(button)
view.addSubview(customView)
NSLayoutConstraint.activate([
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
customView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
customView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
customView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
customView.heightAnchor.constraint(equalToConstant: 100)
])
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setupAnimationCustomView()
}
private func setupAnimationCustomView(){
UIView.animate(withDuration: 1, delay: 0 , options: .curveEaseOut, animations: {
print(self.button.frame.origin.y)
let translationY = self.view.frame.height - self.button.frame.origin.y - self.button.frame.height - self.customView.frame.height - 8
self.customView.transform = CGAffineTransform(translationX: 0, y: translationY * (-1))
}, completion: nil)
}
}
on the animation I calculate the distance that I need to move my customView.
UIKit: how to animate a constraint change with a programmatically created constraint?
One approach:
- create one constraint setting the Bottom of
customTopView
above the Top of the view - create a second constraint setting the Top of
customTopView
below the Top of the view - add
customTopView
as a subview, activating the first constraint - animate
customTopView
into view by deactivating the first constraint and activating the second constraint
Here's a modified version of your showCustomTopView(...)
extension, using a UILabel
as customTopView
-- should work fine with your CustomTopView.instance(withTitle: ...)
:
extension UIView {
func showCustomTopView(withTitle title: NSAttributedString, subtitle: NSAttributedString) {
let customTopView = UILabel()
customTopView.text = title.string
customTopView.backgroundColor = .green
addSubview(customTopView)
customTopView.translatesAutoresizingMaskIntoConstraints = false
let g = self.safeAreaLayoutGuide
// constraint: Bottom of customTopView to Top of self Minus 8-pts
let cvBot = customTopView.bottomAnchor.constraint(equalTo: topAnchor, constant: -8.0)
// constraint: Top of customTopView to Top of self Plus 8-pts
let cvTop = customTopView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0)
NSLayoutConstraint.activate([
customTopView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
customTopView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0),
// activate cvBot, so customTopView is 8-pts above the top of self
cvBot,
])
// execute this async, so the initial view position is set
DispatchQueue.main.async {
// deactivate the Bottom constraint
cvBot.isActive = false
// activate the Top constraint
cvTop.isActive = true
// animate it into view
UIView.animate(withDuration: 0.5, animations: {
self.layoutIfNeeded()
})
}
}
}
SWIFT animation while changing NSLayoutConstraint
as always you should call layoutIfNeeded
to animate a change in a layout constraint. In your case you should call it on the view containing the constraint (which is not immediately obvious to me). Or simple self.view.layoutIfNeeded()
inside the actual animation block:
The example does the animation for you and the animation takes 0.5
second to finish. You can use the overloads of UIView
's animation blocks for a better control on your animations' details.
func scrollViewDidScroll(scrollView: UIScrollView) {
if mapHeight.constant < 400 {
UIView.animateWithDuration(0.5) { () -> Void in
mapHeight.constant = 400
self.view.layoutIfNeeded()
}
tableOfRestaraunts.reloadData()
}
}
func normalSize() {
if mapHeight.constant == 400 {
UIView.animateWithDuration(0.5) { () -> Void in
mapHeight.constant = 200
self.view.layoutIfNeeded()
}
}
}
Update: I didn't realize you haven't the animation block. Updated to include the actual animation block.
Related Topics
Xcode Reference a Framework Instead of Link Binary with Libraries
Didreceiveremotenotification Not Called in Background Mode
Find Number of Spaces in a String in Swift
How to Pair And/Or Bond to Ble on iOS Using Swift Code and an Hm-10 So Data Sent Is Encrypted
Filemanager and Urlsfordirectory Error in Swift 3 Xcode 8
How to Animate Uilabel's Textcolor Change
Keep a UIview or UIviewcontroller on Top of All Others
Dynamic Height for a Uitableview Based on a Dynamic Collection View
Use Elcimagepickercontroller to Pick Video
Default Uifont Size and Weight But Also Support Preferredfontfortextstyle
Native-Like Momentum-Scrolling on Body in iOS Webapp
Sorting Nsarray Containing Nsdate Objects
Gkmatchmaker Invite Handler Deprecated
Is Localstorage on iPad Safari Guaranteed to Be Persistent
How to Schedule Mail Using Gmail API