使用AutoLayout约束动画viewController转换(Swift)

时间:2018-03-21 17:26:30

标签: ios swift xcode autolayout constraints

我正在尝试使用UIViewControllerAnimatedTransitioning委托方法为viewControllers设置动画,我有一些问题。

我见过的所有示例代码都使用框架为视图设置动画,但是我使用的是autolayout,它在动画帧更改时给我带来了问题。

有这两个观点: First View Controller Second View Controller

我希望以这种方式设置从firstVC到secondVC的转换:

Animation

所以,这是我用来做这个动画的代码:

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    let containerView = transitionContext.containerView
    let fromVC = transitionContext.viewController(forKey: .from)! as! CustomView
    let toView = transitionContext.view(forKey: .to)!
    //let cell = fromVC.currentCell //Access to the pressed cell (if needed)

    toView.frame = fromVC.currentFrame //currentFrame is the cell frame saved on fromVC

    toView.autoresizingMask = containerView.autoresizingMask
    toView.layoutIfNeeded()

    containerView.addSubview(toView)

    UIView.animate(withDuration: duration, animations: {

        toView.frame = containerView.frame
        toView.layoutIfNeeded()
    }, completion: { _ in

        transitionContext.completeTransition(true)
    })
}

正如您所看到的,由于框架修改和使用AutoLayout,动画效果不佳。

那么,你觉得我怎么能用约束做这个动画?

谢谢!

1 个答案:

答案 0 :(得分:0)

您需要获取目标视图的参考视图,以设置转换动画。您的源视图和目标视图应该与约束相同。

使用snapShot获取视图以获取参考视图。

然后使用关键帧动画显示转换。在下面的示例代码中使用alpa动画,以使转换感觉连续!

    var originFrame: CGRect! 
    // Orginal frame of card view(starting frame)
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        guard let fromVC = transitionContext.viewController(forKey: .from),
            let toVC = transitionContext.viewController(forKey: .to),
            let snapshot = toVC.view.snapshotView(afterScreenUpdates: true)
            else {
              return
        }

        let containerView = transitionContext.containerView
        let finalFrame = transitionContext.finalFrame(for: toVC)

        snapshot.frame = originFrame
        snapshot.layer.cornerRadius = CardViewController.cardCornerRadius
        snapshot.layer.masksToBounds = true

        containerView.addSubview(toVC.view)
        containerView.addSubview(snapshot)
        toVC.view.isHidden = true
        fromVC.view.alpha = 1
        snapshot.alpha = 0
        let duration = 0.6

        UIView.animateKeyframes(
            withDuration: duration,
            delay: 0,
            options: .calculationModeCubic,
            animations: {
              UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1/2) {
                  fromVC.view.alpha = 1
              }

              UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1) {
                  snapshot.frame = finalFrame
                  fromVC.view.alpha = 0
                  snapshot.alpha = 1
              }
        },
          completion: { _ in
              toVC.view.isHidden = false
              snapshot.removeFromSuperview()
              fromVC.view.layer.transform = CATransform3DIdentity
              transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })

    }