How to Animate a Nslayoutconstraint in Swift

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:

Sample Image

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



Leave a reply



Submit