【问题标题】:Constraint animations will only move up, won't move down约束动画只会向上移动,不会向下移动
【发布时间】:2018-02-22 23:19:45
【问题描述】:

我有两个按钮可以触发两个对象(一个视图和一个 imageView)上的动画,它们的位置由自动布局设置。 (在尝试解决这个问题时,我将目的地简化为屏幕的顶部和底部。):

@objc func upButtonTapped() {
    self.logo.centerYAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
    self.inputsView.bottomAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
    UIView.animate(withDuration: 0.3) {
        self.view.layoutIfNeeded()
    }
    print("Up")
}
@objc func downButtonTapped() {
    self.logo.centerYAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
    self.inputsView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
    UIView.animate(withDuration: 0.3) {
        self.view.layoutIfNeeded()
    }
    print("Down")
}

upButtonTapped 动画可以正常工作,但 downButtonTapped 则不行。在与目的地玩了太久之后,我意识到锚点和约束的组合不会导致对象在屏幕上显示动画。这两个函数都被各自的按钮正确定位,我尝试将每个函数之间的约束更新交换为相同的结果。

如果有帮助,这是我为两个对象设置的初始约束(使用自定义扩展):

logo.anchor(xCenter: view.centerXAnchor,
            yCenter: view.topAnchor, yCenterConstant: view.frame.height / 3,
            width: 65)
inputsView.anchor(bottom: view.safeAreaLayoutGuide.bottomAnchor, bottomConstant: -100,
                  xCenter: view.centerXAnchor,
                  width: view.frame.width * 0.7,
                  height: 200)

谁能告诉我发生了什么/如何解决?

【问题讨论】:

  • 你过度限制了你的观点。在设置新的垂直约束之前,您需要跟踪早期的约束并停用建立视图垂直位置的约束。
  • @vacawama 如果我将两个按钮都设置为在屏幕上向上移动视图,则动画可以正常工作,我可以继续调用它们而不会出现问题。只有当我尝试将它们设置到屏幕底部时,它们才会起作用
  • @vacawama 我做了一个额外的测试,并在动画中添加了一个水平移动,并且发生了同样的事情 - 向左设置动画效果很好,但它们不会向右移动。有什么想法吗?

标签: ios swift animation autolayout


【解决方案1】:

我用一个视图复制了您的结果。您的问题是您的视图受到过度约束,因为您不断添加新约束,但您永远不会删除它们。当视图受到过度约束时,Auto Layout 通过选择要忽略的约束来打破约束。无论出于何种原因,它都有利于“向上”约束。您需要有一个跟踪垂直约束的属性,并且需要在创建和激活新约束之前在该约束上设置isActive = false

这是我的示例的代码。我正在将单个红色方形视图移动到屏幕的顶部和底部。请注意我如何使用属性来跟踪将视图定位在垂直方向的约束,以及我如何使用该属性停用当前约束,然后存储并激活新约束。

class ViewController: UIViewController {

    @IBOutlet weak var redView: UIView!

    @IBOutlet weak var redCenter: NSLayoutConstraint!

    var redCenterConstraint: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()

        // start with the constraint set in the Storyboard
        redCenterConstraint = redCenter
    }

    @IBAction func moveUp(_ sender: UIButton) {
        // deactivate the current constraint
        redCenterConstraint?.isActive = false

        // create the new constraint
        redCenterConstraint = redView.centerYAnchor.constraint(equalTo: self.view.topAnchor, constant: 0)

        // activate the new constraint
        redCenterConstraint?.isActive = true

        // animate the change
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }
    }

    @IBAction func moveDown(_ sender: UIButton) {
        // deactivate the current constraint
        redCenterConstraint?.isActive = false

        // create the new constraint
        redCenterConstraint = redView.centerYAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)

        // activate the new constraint
        redCenterConstraint?.isActive = true

        // animate the change
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }
    }
}

这里是在模拟器中运行的:

【讨论】:

    【解决方案2】:

    试试下面的代码,我只是添加完成处理程序:---

    func downAnimation() {
        UIView.animate(withDuration: 1.4, delay: 0.0, options: [],animations: {
            self.logo.centerYAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
            self.inputsView.bottomAnchor.constraint(equalTo:    self.view.bottomAnchor, constant: 0).isActive = true
        }) { (complete) in
    
            if self.isAnimate{
                self.upAnimation()
            }
        }
    }
    
    func upAnimation() {
        UIView.animate(withDuration: 1.4, delay: 0.0, options: [],animations: {
            self.logo.centerYAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
            self.inputsView.bottomAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
        }) { (complete) in
            if self.isAnimate {
                self.downAnimation()
            }
        }
    }
    

    希望对你有帮助 谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-03
      • 1970-01-01
      • 2010-12-17
      • 1970-01-01
      相关资源
      最近更新 更多