自定义 VC 转换未正确关闭

Posted

技术标签:

【中文标题】自定义 VC 转换未正确关闭【英文标题】:Custom VC Transition not Dismissing Properly 【发布时间】:2019-11-22 07:11:42 【问题描述】:

我正在尝试使用自定义转换在 VC 中重新创建库存 UIAlertAction。我目前的演示工作完美(backgroundView 淡入,“通知”VC 从底部滑出)。我面临的问题是当我解雇 VC 时,backgroundView 不会淡出。就好像它完全绕过了我的动画块。一旦completeTransition 被调用,backgroundView 就会完全消失。怎么了?

class AnimationController: NSObject 
 let backgroundView = UIView()


extension AnimationController:  UIViewControllerAnimatedTransitioning 
  func animateTransition(using transitionContext: UIViewControllerContextTransitioning) 
    let containerView = transitionContext.containerView

    guard let toViewController = transitionContext.viewController(forKey: .to),
        let fromViewController = transitionContext.viewController(forKey: .from) else 
            transitionContext.completeTransition(false)
        return
    
    switch animationType 
    case .present:
        backgroundView.frame = CGRect(x: 0, y: 0, width: toViewController.view.frame.width, height: fromViewController.view.frame.height)
        backgroundView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)
        backgroundView.alpha = 0
        containerView.addSubview(backgroundView)

        let viewToAnimate = toViewController.view!
        containerView.addSubview(viewToAnimate)

        toViewController.view.clipsToBounds = true

        viewToAnimate.frame = CGRect(x: 0, y: viewToAnimate.frame.maxY, width: viewToAnimate.frame.width, height: viewToAnimate.frame.height)

        let duration = transitionDuration(using: transitionContext)

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations:  
            self.backgroundView.alpha = 1.0
            viewToAnimate.transform = CGAffineTransform(translationX: 0, y: -viewToAnimate.frame.height)
        )  _ in
            transitionContext.completeTransition(true)
        
    case .dismiss:

        containerView.addSubview(fromViewController.view!)

        let testView = fromViewController.view!

        backgroundView.frame = CGRect(x: 0, y: 0, width: testView.frame.width, height: testView.frame.height)
        backgroundView.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1)

        let duration = transitionDuration(using: transitionContext)

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations:  
            self.backgroundView.alpha = 0.0
            testView.transform = CGAffineTransform(translationX: 0, y: testView.frame.height)
            print("backgroundView Doesn't fade out")
        )  _ in
            print("backgroundView disappears here")
            transitionContext.completeTransition(true)
        
    

【问题讨论】:

您是否在新的*** VC 中注册了过渡委托? @SanthoshSKashyap 它调用 animateTransition 函数,所以我认为这不是问题...... 看看一个有效的例子会有帮助吗? github.com/mattneub/custom-alert-view-ios7 @matt 谢谢你,我正在尝试将视图动画化为 2 个单独的元素(背景 + 视图)。此示例将其动画化为单个元素... 只是预感,你试过在主线程上调度它吗?接下来要尝试的是使用图层不透明度而不是视图 alpha。 【参考方案1】:

你可以尝试这样展示

//where DevolucionVC is you ViewController 
    if let controller = DevolucionVC() as? DevolucionVC 
                if let window = self.window, let rootViewController = window.rootViewController 
                    var currentController = rootViewController
                    while let presentedController = currentController.presentedViewController 
                        currentController = presentedController
                    
                    currentController.present(controller, animated: true, completion: nil)
                
            

您可以稍后通过简单地使用来关闭它

 dismiss(animated: true, completion: nil)

【讨论】:

【参考方案2】:

试试这个

暂时替换此代码

    backgroundView.frame = CGRect(x: 0, y: 0, width: toViewController.view.frame.width, height: fromViewController.view.frame.height)
    backgroundView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)
    backgroundView.alpha = 0
    containerView.addSubview(backgroundView)

    let transition = CATransition()
    transition.duration = 0.5
    transition.type = CATransitionType.moveIn
    transition.subtype = CATransitionSubtype.fromTop
    containerView.layer.add(transition, forKey: kCATransition)

对于 Dismiss 替换此代码

  containerView.addSubview(fromViewController.view!)
  let transition = CATransition()
  transition.duration = 0.5
  transition.type = CATransitionType.fade
  containerView.layer.add(transition, forKey: kCATransition)
  backgroundView.frame = CGRect(x: 0, y: 0, width: testView.frame.width, height: testView.frame.height)
  backgroundView.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
  self.backgroundView.alpha = 0.0

【讨论】:

我刚刚添加了这段代码,目前它根本不会淡入背景视图。我错过了什么吗?【参考方案3】:

您的问题是您正在处理 AnimationController 的两个单独实例,因此是 backgroundView 的两个单独实例。一个实例为演示而实例化,而另一个实例为解雇而实例化。请注意,在您的 case .present: 块中,您正在调用 containerView.addSubview(backgroundView),但您在 case .dismiss: 块中没有这样做。因此,case .dismiss: 块中的 backgroundView 实例甚至不是视图层次结构的一部分。

您需要做的是在您的第一个动画完成块中调用self.backgroundView.removeFromSuperview()。然后在您的case .dismiss: 中,您需要再次调用containerView.addSubview(backgroundView)

试试这个...

    switch animationType 
    case .present:

        // ...

        containerView.addSubview(backgroundView)

        // ...

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations:  
            self.backgroundView.alpha = 1.0
            viewToAnimate.transform = CGAffineTransform(translationX: 0, y: -viewToAnimate.frame.height)
        )  _ in
            self.backgroundView.removeFromSuperview()
            transitionContext.completeTransition(true)
        
    case .dismiss:

        // ...

        containerView.addSubview(backgroundView)

        containerView.addSubview(fromViewController.view!)

        // ...

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations:  
            self.backgroundView.alpha = 0.0
            testView.transform = CGAffineTransform(translationX: 0, y: testView.frame.height)
            print("backgroundView Doesn't fade out")
        )  _ in
            print("backgroundView disappears here")
            transitionContext.completeTransition(true)
        
    

【讨论】:

以上是关于自定义 VC 转换未正确关闭的主要内容,如果未能解决你的问题,请参考以下文章

没有segue的自定义关闭过渡

设置 NavigationController.Viewcontrollers 崩溃(使用自定义转换)

Wix 的 VC++ 自定义操作

使用删除与隐藏时未调用自定义动画

自定义 UITableViewCell 未正确加载

从自定义表格视图单元格获取数据到另一个 VC?