Animate UIView 转换立即发生,而不是超过持续时间值

Animate UIView transform happens instantly instead of over duration value

我正在尝试以与操作表的显示方式类似的方式为屏幕上的视图设置动画。

我的路由器显示 CustomCardViewController 具有叠加背景。

短暂延迟后,我希望 containerView 也能从底部看到动画。

相反,正在发生的事情只是出现在适当的位置。转场之间没有动画

final class CustomCardViewController: UIViewController {

  private let backgroundMask: UIView = {
    let view = UIView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .init(white: 0, alpha: 0.3)
    return view
  }()

  private lazy var containerView: UIView = {
    let view = UIView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .red
    view.transform = .init(translationX: 0, y: view.frame.height)
    return view
  }()

  override func viewDidLoad() {
    super.viewDidLoad()
    backgroundMask.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTapToDismiss)))

    modalPresentationStyle = .overFullScreen

    [backgroundMask, containerView].forEach(view.addSubview(_:))

    NSLayoutConstraint.activate([
      backgroundMask.topAnchor.constraint(equalTo: view.topAnchor),
      backgroundMask.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      backgroundMask.bottomAnchor.constraint(equalTo: view.bottomAnchor),
      backgroundMask.trailingAnchor.constraint(equalTo: view.trailingAnchor),

      containerView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 24),
      containerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -24),
      containerView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -24),
      containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 200)

    ])

    UIView.animate(withDuration: 5, delay: 0.33, options: .curveEaseOut, animations: {
      self.containerView.transform = .identity
    }, completion: nil)

  }
}

private extension CustomCardViewController {
  @objc func onTapToDismiss() {
    dismiss(animated: false, completion: nil)
  }
}

您需要从另一个生命周期方法调用您的动画块。您无法从 viewDidLoad 触发此操作,因为视图刚刚加载,屏幕上还没有任何内容。

尝试使用 viewDidAppear

对于动画,您需要更新要设置动画的约束的常量。在这里,由于您尝试从底部开始设置动画,因此在本例中您需要更新垂直约束,即底部约束。这是动画代码:

final class CustomCardViewController: UIViewController {
    //..
    override func viewDidLoad() {
        super.viewDidLoad()

        NSLayoutConstraint.activate([
            // remove bottom constraint from here
        ])

        containerViewBottomConstraint = containerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 250)
        containerViewBottomConstraint?.isActive = true
    }

    var containerViewBottomConstraint: NSLayoutConstraint? // declare bottom constraint

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        containerViewBottomConstraint?.constant = -24

        UIView.animate(withDuration: 5, delay: 0.33, options: .curveEaseOut, animations: {
            self.view.layoutIfNeeded()
        })
    }
}