如何使用屏幕外的自动布局锚定位视图

How to position a view using Auto Layout anchors outside the screen

如何使用屏幕外的自动布局锚点将视图定位到右侧?我想稍后将其动画化到中心位置。

func setup(){
    _ = firstNameTextField.anchor(nil, 
                                  left: view.leftAnchor, 
                                bottom: lastnameTextField.topAnchor, 
                                 right: view.rightAnchor, 
                           topConstant: 16, 
                          leftConstant: 16, 
                        bottomConstant: 8, 
                         rightConstant: 16, 
                         widthConstant: 0, 
                        heightConstant: 46)
}

明确定义您的约束可能比使用 "helper" 函数更有好处...它可以让您更容易理解正在发生的事情。

就是说,您希望将字段的 left 锚点约束到视图的 right 锚点,这将把它放在 "off-screen" 上。然后您可以更改它以将字段设置为动画... "slide it in from the right".

为此,创建一个 "start" 约束和一个 "end" 约束:

// starting constraint will be leading edge of field 16-pts to the right of view's right edge (off-screen)
firstNameLeadingConstraintStart = firstNameTextField.leadingAnchor.constraint(equalTo: view.trailingAnchor, constant: 16.0)

// ending constraint will be leading edge of field 16-pts from view's left edge
firstNameLeadingConstraintEnd   = firstNameTextField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16.0)

将其设置为动画:

    // de-activate starting constraint
    self.firstNameLeadingConstraintStart.isActive = false

    // activate ending constraint
    self.firstNameLeadingConstraintEnd.isActive = true

    // animate the change
    UIView.animate(withDuration: 0.75, animations: {
        self.view.layoutIfNeeded()
    })

这是一个基本示例。它包括一个触发动画的按钮:

class SampleViewController: UIViewController {

    var firstNameTextField: UITextField = {
        let v = UITextField()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.borderStyle = .roundedRect
        v.backgroundColor = .orange  // to make it easy to see
        return v
    }()

    var button: UIButton = {
        let v = UIButton()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.setTitle("Tap Me", for: .normal)
        v.setTitleColor(.blue, for: .normal)
        return v
    }()

    // constraint for starting position of field
    var firstNameLeadingConstraintStart: NSLayoutConstraint!

    // constraint for ending position of field
    var firstNameLeadingConstraintEnd: NSLayoutConstraint!

    override func viewDidLoad() {

        view.addSubview(firstNameTextField)

        NSLayoutConstraint.activate([

            // top of field 16-pts from top of view
            firstNameTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16.0),

            // width of field should be width of view minus 32 (16-pts padding on each side)
            firstNameTextField.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor, constant: -32.0),

            // height of field 46-pts
            firstNameTextField.heightAnchor.constraint(equalToConstant: 46.0),

            ])

        // starting constraint will be leading edge of field 16-pts to the right of view's right edge (off-screen)
        firstNameLeadingConstraintStart = firstNameTextField.leadingAnchor.constraint(equalTo: view.trailingAnchor, constant: 16.0)

        // ending constraint will be leading edge of field 16-pts from view's left edge
        firstNameLeadingConstraintEnd   = firstNameTextField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16.0)

        // activate the starting constraint
        firstNameLeadingConstraintStart.isActive = true

        // add a button so we can trigger the animation
        view.addSubview(button)
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            ])
        button.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)
    }

    func animateField() -> Void {

        // de-activate starting constraint
        self.firstNameLeadingConstraintStart.isActive = false

        // activate ending constraint
        self.firstNameLeadingConstraintEnd.isActive = true

        // animate the change
        UIView.animate(withDuration: 0.75, animations: {
            self.view.layoutIfNeeded()
        })

    }

    @objc func didTap(_ sender: Any) {
        animateField()
    }

}