UIViewControllerAnimatedTransitioning:屏幕在自定义视图下不断变黑

时间:2017-07-28 08:19:07

标签: ios swift animation uiviewcontroller

我在SO(以及其他地方)找到了许多相关主题,但仍无法找到问题的解决方案。我想使用UIViewControllerTransitioningDelegate在我的视图中显示自定义提醒。首先,在我的初始视图控制器中,这是调用:

@IBAction func tappedButton(_ sender: Any) { 
    MyAlertViewController.presentIn(viewController: self)
}

这里是MyAlertViewController的代码:

import UIKit

open class MyAlertViewController: UIViewController, UIViewControllerTransitioningDelegate {

    @IBOutlet weak var overlayView: UIView?
    @IBOutlet weak var alertView: UIView?
    @IBOutlet weak var alertCenterYConstraint: NSLayoutConstraint?

    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: "MyAlertView", bundle: nil)
        self.transitioningDelegate = self
    }

    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    static func presentIn(viewController: UIViewController) {
        let alertViewController = MyAlertViewController()

        if Thread.isMainThread {
             viewController.present(alertViewController, animated: true, completion: nil)
        } else {
            DispatchQueue.main.async {
                viewController.present(alertViewController, animated: true, completion: nil)
            }
        }
    }

    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return MyDismissAlertViewAnimationController()
    }

    public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return MyPresentAlertViewAnimationController()
    }
}

class MyPresentAlertViewAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let toViewController: MyAlertViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! MyAlertViewController
        let duration = self.transitionDuration(using: transitionContext)

        let containerView = transitionContext.containerView
        toViewController.view.frame = containerView.frame
        containerView.addSubview(toViewController.view)

        toViewController.overlayView?.alpha = 0.0
        UIView.animate(withDuration: duration, animations: {
            toViewController.overlayView?.alpha = 0.6
        })

        let finishFrame = toViewController.alertView?.frame
        var startingFrame = finishFrame
        startingFrame?.origin.y = -((finishFrame?.height)!)
        toViewController.alertView?.frame = startingFrame!

        UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 1.0, options: .layoutSubviews, animations: {
            toViewController.alertView?.frame = finishFrame!
        }, completion: { result in
            transitionContext.completeTransition(result)
        })
    }
}

class MyDismissAlertViewAnimationController: NSObject,  UIViewControllerAnimatedTransitioning {
    public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let fromViewController: MyAlertViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! MyAlertViewController
        let duration = self.transitionDuration(using: transitionContext)

        UIView.animate(withDuration: duration, animations: {
            fromViewController.overlayView?.alpha = 0.0
        })

        var finishFrame = fromViewController.alertView?.frame
        finishFrame?.origin.y = -(finishFrame?.height)!
        finishFrame?.origin.y = fromViewController.isDismissingByBottom ? fromViewController.view.frame.size.height : -(finishFrame?.height)!

        UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .layoutSubviews, animations: {
            fromViewController.alertView?.frame = finishFrame!
        }, completion: { result in
            transitionContext.completeTransition(true)
        })
    }
}

动画效果很好,只有在调用completeTransition()后才能显示黑屏,如下所示:

enter image description here

感谢您的帮助......

1 个答案:

答案 0 :(得分:1)

我认为您需要像这样设置背景颜色:

self.view.backgroundColor = .clear

这将确保您看到的背景不仅仅是模态的背景颜色。

或者通过制作模态演示样式overCurrentContext

来阻止从屏幕上移除呈现视图控制器
self.modalPresentationStyle = .overCurrentContext