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

Tig*_*ran 2 animation uiview ios swift

我创建了一个按钮,它连接到顶部、前导和尾随并且具有固定的高度。当我点击按钮时,新的 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()
    }
}



}
Run Code Online (Sandbox Code Playgroud)

即使我将高度设置为 300 也没有任何效果

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

在此处输入图片说明

当人们从故事板创建 IBOutlet 然后更改其常量值时,我看到了很多教程。但我想知道如何以编程方式做到这一点。

Ahm*_*d F 7

您的代码中的问题是您试图通过说 (in )来重新激活另一个描述 高度的约束:myViewexpandMenu()

myView.heightAnchor.constraint(equalToConstant: 300).isActive = true
Run Code Online (Sandbox Code Playgroud)

我假设您收到类似于以下内容的运行时警告:

[LayoutConstraints] 无法同时满足约束。可能以下列表中的至少一项约束是您不想要的。试试这个: (1) 查看每个约束并尝试找出您不期望的;(2) 找到添加不需要的约束或约束的代码并修复它。( "NSLayoutConstraint:0x60400008e5b0 UIView:0x7fa16a419450.height == 100 (active)>", "NSLayoutConstraint:0x608000097e30 UIView:0x7fa16a419450.heightactive) ==>300)

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

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

意味着myView已经有一个高度约束,即(in viewDidLoad()):

myView.heightAnchor.constraint(equalToConstant: 100).isActive = true
Run Code Online (Sandbox Code Playgroud)

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

将 a 声明NSLayoutConstraint为实例变量:

var myViewHeightConstraint: NSLayoutConstraint!
Run Code Online (Sandbox Code Playgroud)

并在viewDidLoad()

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

代替:

myView.heightAnchor.constraint(equalToConstant: 100).isActive = true
Run Code Online (Sandbox Code Playgroud)

最后,在expandMenu()

myViewHeightConstraint.constant = 300
Run Code Online (Sandbox Code Playgroud)

代替:

myView.heightAnchor.constraint(equalToConstant: 300).isActive = true
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明


此外:

如果您的目标是让相同的按钮实现展开/折叠行为,则只需将其实现为 (in expandMenu()):

myViewHeightConstraint.constant = myViewHeightConstraint.constant == 300 ? 100 : 300
Run Code Online (Sandbox Code Playgroud)