动画约束改变 UIViewController

Animate constraints change UIViewController

我有 "error" 视图,它位于导航栏上方并隐藏。发生错误时,我希望该视图从顶部顺利显示。我试过了:

class AuthViewController: UIViewController {

  let error: ErrorView = {
    let error = ErrorView()
    error.setup()
    return error
  }()
  var topAnchor: NSLayoutConstraint!
  var botAnchor: NSLayoutConstraint!

  override func viewDidLoad() {
    setupErrorView()
  }

  private func setupErrorView(){
    view.addSubview(error)
    botAnchor = error.bottomAnchor.constraint(equalTo: view.topAnchor)
    botAnchor.isActive = true
    topAnchor = error.topAnchor.constraint(equalTo: view.topAnchor, constant: CGFloat(Offsets.navigationAndStatusBarHeight))
    topAnchor.isActive = false
    error.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    error.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
  }

  func showError(_ text: String){
    UIView.animate(withDuration: 2.0) {[weak self] in
      guard let weakSelf = self else { return }
      print("attempt to animate")
      weakSelf.error.show(text)
      weakSelf.botAnchor.isActive = false
      weakSelf.topAnchor.isActive = true
      weakSelf.view.setNeedsLayout()
    }
  }
}

class ErrorView: UIView {

  private var label: UILabel = {
    return LabelSL.regular()
  }()

  fileprivate func setup(){
    translatesAutoresizingMaskIntoConstraints = false
    backgroundColor = Theme.Color.orange.value
    addSubview(label)
  }

  fileprivate func show(_ text: String){
    let sideOffset: CGFloat = 10
    let verticalOffset: CGFloat = 10
    label.text = text
    label.topAnchor.constraint(equalTo: topAnchor, constant: verticalOffset).isActive = true
    label.leftAnchor.constraint(equalTo: leftAnchor, constant: sideOffset).isActive = true
    label.rightAnchor.constraint(equalTo: rightAnchor, constant: -sideOffset).isActive = true
    label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -verticalOffset).isActive = true
  }
}

动画应该在调用 func showError(_ text: String){ 方法时完成,但事实并非如此。视图立即出现。

您试图以错误的方式为约束设置动画。您应该在动画块之外设置约束,并且只在动画中设置 layoutIfNeeded

func showError(_ text: String){
    botAnchor.isActive = false
    topAnchor.isActive = true
    error.show(text)
    UIView.animate(withDuration: 2.0) {
        self.view.layoutIfNeeded()
    }
}