trying to animate a constraint in swift

后端 未结 6 1928
离开以前
离开以前 2020-11-29 16:00

I have a UITextField that I want to enlarge its width when tapped on. I set up the constraints and made sure the constraint on the left has the lower priority t

6条回答
  •  北海茫月
    2020-11-29 16:36

    With Swift 5 and iOS 12.3, according to your needs, you may choose one of the 3 following ways in order to solve your problem.


    #1. Using UIView's animate(withDuration:animations:) class method

    animate(withDuration:animations:) has the following declaration:

    Animate changes to one or more views using the specified duration.

    class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void)
    

    The Playground code below shows a possible implementation of animate(withDuration:animations:) in order to animate an Auto Layout constraint's constant change.

    import UIKit
    import PlaygroundSupport
    
    class ViewController: UIViewController {
    
        let textView = UITextView()
        lazy var heightConstraint = textView.heightAnchor.constraint(equalToConstant: 50)
    
        override func viewDidLoad() {
            view.backgroundColor = .white
            view.addSubview(textView)
    
            textView.backgroundColor = .orange
            textView.isEditable = false
            textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    
            textView.translatesAutoresizingMaskIntoConstraints = false
            textView.topAnchor.constraint(equalToSystemSpacingBelow: view.layoutMarginsGuide.topAnchor, multiplier: 1).isActive = true
            textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
            textView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor).isActive = true
            heightConstraint.isActive = true
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doIt(_:)))
            textView.addGestureRecognizer(tapGesture)
        }
    
        @objc func doIt(_ sender: UITapGestureRecognizer) {
            heightConstraint.constant = heightConstraint.constant == 50 ? 150 : 50
            UIView.animate(withDuration: 2) {
                self.view.layoutIfNeeded()
            }
        }
    
    }
    
    PlaygroundPage.current.liveView = ViewController()
    

    #2. Using UIViewPropertyAnimator's init(duration:curve:animations:) initialiser and startAnimation() method

    init(duration:curve:animations:) has the following declaration:

    Initializes the animator with a built-in UIKit timing curve.

    convenience init(duration: TimeInterval, curve: UIViewAnimationCurve, animations: (() -> Void)? = nil)
    

    The Playground code below shows a possible implementation of init(duration:curve:animations:) and startAnimation() in order to animate an Auto Layout constraint's constant change.

    import UIKit
    import PlaygroundSupport
    
    class ViewController: UIViewController {
    
        let textView = UITextView()
        lazy var heightConstraint = textView.heightAnchor.constraint(equalToConstant: 50)
    
        override func viewDidLoad() {
            view.backgroundColor = .white
            view.addSubview(textView)
    
            textView.backgroundColor = .orange
            textView.isEditable = false
            textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    
            textView.translatesAutoresizingMaskIntoConstraints = false
            textView.topAnchor.constraint(equalToSystemSpacingBelow: view.layoutMarginsGuide.topAnchor, multiplier: 1).isActive = true
            textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
            textView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor).isActive = true
            heightConstraint.isActive = true
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doIt(_:)))
            textView.addGestureRecognizer(tapGesture)
        }
    
        @objc func doIt(_ sender: UITapGestureRecognizer) {
            heightConstraint.constant = heightConstraint.constant == 50 ? 150 : 50
            let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: {
                self.view.layoutIfNeeded()
            })
            animator.startAnimation()
        }
    
    }
    
    PlaygroundPage.current.liveView = ViewController()
    

    #3. Using UIViewPropertyAnimator's runningPropertyAnimator(withDuration:delay:options:animations:completion:) class method

    runningPropertyAnimator(withDuration:delay:options:animations:completion:) has the following declaration:

    Creates and returns an animator object that begins running its animations immediately.

    class func runningPropertyAnimator(withDuration duration: TimeInterval, delay: TimeInterval, options: UIViewAnimationOptions = [], animations: @escaping () -> Void, completion: ((UIViewAnimatingPosition) -> Void)? = nil) -> Self
    

    The Playground code below shows a possible implementation of runningPropertyAnimator(withDuration:delay:options:animations:completion:) in order to animate an Auto Layout constraint's constant change.

    import UIKit
    import PlaygroundSupport
    
    class ViewController: UIViewController {
    
        let textView = UITextView()
        lazy var heightConstraint = textView.heightAnchor.constraint(equalToConstant: 50)
    
        override func viewDidLoad() {
            view.backgroundColor = .white
            view.addSubview(textView)
    
            textView.backgroundColor = .orange
            textView.isEditable = false
            textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    
            textView.translatesAutoresizingMaskIntoConstraints = false
            textView.topAnchor.constraint(equalToSystemSpacingBelow: view.layoutMarginsGuide.topAnchor, multiplier: 1).isActive = true
            textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
            textView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor).isActive = true
            heightConstraint.isActive = true
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doIt(_:)))
            textView.addGestureRecognizer(tapGesture)
        }
    
        @objc func doIt(_ sender: UITapGestureRecognizer) {
            heightConstraint.constant = heightConstraint.constant == 50 ? 150 : 50
            UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 2, delay: 0, options: [], animations: {
                self.view.layoutIfNeeded()
            })
        }
    
    }
    
    PlaygroundPage.current.liveView = ViewController()
    

提交回复
热议问题