如何在不制作IBOutlet的情况下以编程方式在Swift中为UIView高度约束设置动画?

时间:2018-06-21 06:36:26

标签: ios swift animation uiview

我创建了一个按钮,该按钮连接到顶部,开头和结尾并具有固定的高度。当我点击按钮时,新的UIView实例应与动画一起出现。

import UIKit

class ViewController: UIViewController {

var topButton = UIButton()
var myView = UIView()

override func viewDidLoad() {
    super.viewDidLoad()

    topButton = UIButton(type: .roundedRect)
    topButton.setTitle("Add Acctivity", for: .normal)
    topButton.backgroundColor = UIColor.purple
    topButton.setTitleColor(UIColor.white, for: .normal)
    topButton.titleLabel?.font = UIFont(name: "System", size: 26)
    topButton.translatesAutoresizingMaskIntoConstraints = false
    topButton.addTarget(self, action: #selector(expandMenu), for: .touchUpInside)
    view.addSubview(topButton)

    topButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
    topButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
    topButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
    topButton.heightAnchor.constraint(equalToConstant: 70).isActive = true

    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)
    myView.topAnchor.constraint(equalTo: view.topAnchor, constant: 70).isActive = true
    myView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
    myView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
    myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

}

@objc func expandMenu() {

   myView.heightAnchor.constraint(equalToConstant: 300).isActive = true

    UIView.animate(withDuration: 1) {

        self.view.layoutIfNeeded()
    }
}



}

Nothing is working even I put the height to be 300

有趣的是,当我将高度设置为小于其初始值时,动画就会起作用。

enter image description here

当人们从情节提要中创建IBOutlet然后更改其恒定值时,我看到了许多教程。但是我想知道如何以编程方式做到这一点。

2 个答案:

答案 0 :(得分:3)

您的代码中的问题是您试图重新激活另一个描述myView高度的约束,方法是说(在expandMenu()中):

myView.heightAnchor.constraint(equalToConstant: 300).isActive = true

我认为您会收到类似于以下内容的运行时警告:

  

[LayoutConstraints]无法同时满足约束。     以下列表中的约束中至少有一个是   你不要试试这个:(1)查看每个约束并尝试   找出你不期望的东西; (2)找到添加了   不必要的约束或约束并进行修复。 (       “ NSLayoutConstraint:0x60400008e5b0 UIView:0x7fa16a419450.height == 100(活动)>”,       “ NSLayoutConstraint:0x608000097e30 UIView:0x7fa16a419450.height == 300(活动)>”   )

     

将尝试通过打破约束来恢复   

     

在UIViewAlertForUnsatisfiableConstraints处创建符号断点   在调试器中捕获它。中的方法   UIView中列出的UIConstraintBasedLayoutDebugging类别,在    可能也有帮助。

表示myView已经有一个高度限制,即(在viewDidLoad()中):

myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

您应该做的是改为更改同一约束的constant值。您可以这样实现:

NSLayoutConstraint声明为实例变量:

var myViewHeightConstraint: NSLayoutConstraint!

viewDidLoad()中的

myViewHeightConstraint = NSLayoutConstraint(item: myView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: 100)
myViewHeightConstraint.isActive = true

代替:

myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

最后,在expandMenu()中:

myViewHeightConstraint.constant = 300

代替:

myView.heightAnchor.constraint(equalToConstant: 300).isActive = true

输出:

enter image description here


此外:

如果您要让同一按钮实现展开/折叠行为,则只需将其实现为(在expandMenu()中):

myViewHeightConstraint.constant = myViewHeightConstraint.constant == 300 ? 100 : 300

答案 1 :(得分:1)

constraint方法返回一个NSLayoutConstraint。您可以将其分配给类级变量:

var heightConstraint: NSLayoutConstraint!

override func viewDidLoad() {
    // ...

    heightConstraint = myView.heightAnchor.constraint(equalToConstant: 100)
    heightConstraint.isActive = true
}

然后您将拥有一个属性heightConstraint,它非常类似于IBOutlet。您可以像对IBOutlet约束进行动画处理一样对它进行动画处理。