首页 文章

尝试在swift中设置约束动画

提问于
浏览
199

我有一个UITextField,我想在点击时放大它的宽度 . 我设置了约束,并确保左边的约束优先级低于我试图在右边设置动画的约束 .

这是我尝试使用的代码 .

// move the input box
    UIView.animateWithDuration(10.5, animations: {
        self.nameInputConstraint.constant = 8
        }, completion: {
            (value: Bool) in
            println(">>> move const")
    })

这有效,但它似乎只是瞬间发生,似乎没有任何动作 . 我试着设置它10秒钟以确保我没有遗漏任何东西,但我得到了相同的结果 .

nameInputConstraint是我控制拖动以从IB连接到我的类的约束的名称 .

感谢您的帮助!

6 回答

  • -1

    您需要先更改约束,然后为更新设置动画 .

    self.nameInputConstraint.constant = 8
    UIView.animateWithDuration(0.5) {
        self.view.layoutIfNeeded()
    }
    

    在Swift 3.0中:

    UIView.animate(withDuration: 0.5) {
        self.view.layoutIfNeeded()
    }
    
  • 559

    SWIFT 4.x :

    self.mConstraint.constant = 100.0
    UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
    }
    

    完成示例:

    self.mConstraint.constant = 100
    UIView.animate(withDuration: 0.3, animations: {
            self.view.layoutIfNeeded()
        }, completion: {res in
            //Do something
    })
    
  • 6

    使用Swift 4.1和iOS 11,根据您的需要,您可以选择以下3种方法之一来解决您的问题 .


    #1 . 使用UIView的animate(withDuration:animations :)类方法

    animate(withDuration:animations:)有以下声明:

    使用指定的持续时间对一个或多个视图进行动画更改 .

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

    下面的Playground代码显示了 animate(withDuration:animations:) 的可能实现,以便为Auto Layout约束的常量更改设置动画 .

    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.constraintEqualToSystemSpacingBelow(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 . 使用UIViewPropertyAnimator的init(duration:curve:animations :) initialiser和startAnimation()方法

    init(duration:curve:animations:)有以下声明:

    使用内置的UIKit定时曲线初始化动画师 .

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

    下面的Playground代码显示了 init(duration:curve:animations:)startAnimation() 的可能实现,以便为Auto Layout约束的常量更改设置动画 .

    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.constraintEqualToSystemSpacingBelow(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 . 使用UIViewPropertyAnimator的runningPropertyAnimator(withDuration:delay:options:animations:completion :)类方法

    runningPropertyAnimator(withDuration:delay:options:animations:completion:)有以下声明:

    创建并返回一个动画对象,该对象立即开始运行其动画 .

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

    下面的Playground代码显示了 runningPropertyAnimator(withDuration:delay:options:animations:completion:) 的可能实现,以便为Auto Layout约束的常量更改设置动画 .

    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.constraintEqualToSystemSpacingBelow(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()
    
  • 6

    指出 view.layoutIfNeeded() 仅适用于视图子视图非常重要 .

    因此,要为视图约束设置动画,必须在视图到动画 superview 上调用它,如下所示:

    topConstraint.constant = heightShift
    
        UIView.animate(withDuration: 0.3) {
    
            // request layout on the *superview*
            self.view.superview?.layoutIfNeeded()
        }
    

    简单布局的示例如下:

    class MyClass {
    
        /// Container view
        let container = UIView()
            /// View attached to container
            let view = UIView()
    
        /// Top constraint to animate
        var topConstraint = NSLayoutConstraint()
    
    
        /// Create the UI hierarchy and constraints
        func createUI() {
            container.addSubview(view)
    
            // Create the top constraint
            topConstraint = view.topAnchor.constraint(equalTo: container.topAnchor, constant: 0)
    
    
            view.translatesAutoresizingMaskIntoConstraints = false
    
            // Activate constaint(s)
            NSLayoutConstraint.activate([
               topConstraint,
            ])
        }
    
        /// Update view constraint with animation
        func updateConstraint(heightShift: CGFloat) {
            topConstraint.constant = heightShift
    
            UIView.animate(withDuration: 0.3) {
    
                // request layout on the *superview*
                self.view.superview?.layoutIfNeeded()
            }
        }
    }
    
  • 3

    就我而言,我只更新了自定义视图 .

    // DO NOT LIKE THIS
    customView.layoutIfNeeded()    // Change to view.layoutIfNeeded()
    UIView.animate(withDuration: 0.5) {
       customViewConstraint.constant = 100.0
       customView.layoutIfNeeded() // Change to view.layoutIfNeeded()
    }
    
  • 15

    观看this .

    视频说您需要添加 self.view.layoutIfNeeded() ,如下所示:

    UIView.animate(withDuration: 1.0, animations: {
           self.centerX.constant -= 75
           self.view.layoutIfNeeded()
    }, completion: nil)
    

相关问题