2

I'm trying to animate a textfield with a custom class, when I change my left constraint from 0 to (self.bounds.width - self.bounds.width/3) the animation is not smooth, but when I set it back to 0 it works perfectly.

Here is part of my custom class:

lazy var leftConstraint = NSLayoutConstraint(item: placeholderLabel, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 0)


required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    self.delegate = self
    self.addSubview(placeholderLabel)
    self.bringSubview(toFront: self)
    addConstraints()
}

func addConstraints() {

    placeholderLabel.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint(item: placeholderLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: self.bounds.height).isActive = true

    self.leftConstraint.isActive = true

    NSLayoutConstraint(item: placeholderLabel, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: 0).isActive = true

    NSLayoutConstraint(item: placeholderLabel, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0).isActive = true


}


func textFieldDidBeginEditing(_ textField: UITextField) {
    animate(constant: self.bounds.width - self.bounds.width/3)
    self.bringSubview(toFront: placeholderLabel)

}


func textFieldDidEndEditing(_ textField: UITextField) {
    if (textField.text?.isEmpty)!{
        animate(constant: 0)
        self.bringSubview(toFront: self)
    }
}


func animate(constant: CGFloat) {

    self.leftConstraint.constant = constant

    UIView.animate(withDuration: 0.15) {
        self.layoutIfNeeded()
    }
}
Sergio Trejo
  • 632
  • 8
  • 23

2 Answers2

2

Possible reason animation is not smooth

func animate(constant: CGFloat) {
    /// Modifying Constraint out of animation
    /// This will animate in micro seconds and you wont get a 
    /// Smooth Animation
    self.leftConstraint.constant = constant
    /// Take this Line (Cut)

    UIView.animate(withDuration: 2) {
        /// Animation will take time to Happen
        self.leftConstraint.constant = constant
        /// Need to call this inside animation block
        self.view.layoutIfNeeded()
    }
}

Tried code

import UIKit

class ViewController: UIViewController
{
    private var customView : UIView?
    private var leftConstraint : NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        customView = UIView()
        customView?.backgroundColor = .red
        leftConstraint = NSLayoutConstraint()
        addConstraints()

        DispatchQueue.main.async {
            self.animateView()
        }
    }

    func addConstraints(){
        self.view.addSubview(customView!)
        customView?.translatesAutoresizingMaskIntoConstraints = false
        leftConstraint = customView?.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 50)
        leftConstraint?.isActive = true
        customView?.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -50).isActive = true
        customView?.heightAnchor.constraint(equalToConstant: 50).isActive = true
        customView?.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
    }

    func animateView(){
        UIView.animate(withDuration: 2) {
            /// Animation will take time to Happen
            self.leftConstraint?.constant = 100
            /// Need to call this inside animation block
            self.view.layoutIfNeeded()
        }
    }
}

Output

enter image description here

iOS Geek
  • 4,825
  • 1
  • 9
  • 30
  • Hi @iOS Geek thanks for you answer, I tried your suggention, and its working but not as I expected. The label inside the textfield is not sticking to the right when the animantion is happening. Even if I use this line placeholderLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true – Sergio Trejo May 22 '18 at 14:32
  • if found the solution. I had to set a width constraint to the textfield instead of triailing and leading – Sergio Trejo May 22 '18 at 15:01
0

Try using CGAffineTransform instead of animating constraints. It can achieve any king of transformation (translation, rotation, scaling). Along with the options of the animate function, you can achieve pretty much anything

Example of translation animation:

 UIView.animate(withDuration: 0.7, delay: 0,
                   usingSpringWithDamping: 1, initialSpringVelocity: 0,
                   options: .curveEaseOut, animations:
        {

            self.anyElement.transform = CGAffineTransform(
                 translationX: 0, 
                 y: 100)

    }, completion:
        { (success) in

            self.anyElement.transform = .identity
    })
vbuzze
  • 930
  • 1
  • 11
  • 25