0

I made a custom modal transition by using UIViewControllerAnimatedTransitioning. After the transition has completed, a modally shown view controller fills part of parent view that some part of parent view controller is still visible.

I need to know how to detect tap on outside of shown view controller(or partially shown parent view controller) so I can use it to close the modal. I understand how to add gesture to a view but I cannot find which view to add a gesture to.

I looked through stackoverflow but there aren't example specifically for custom modal transition.

Here is a code for custom transition

class PartialSlideInAnimationController: NSObject, UIViewControllerAnimatedTransitioning {

    var direction: SlideAnimationDirectionStyle

    var duration: TimeInterval = 0.125
    var presentedControllerWidth: CGFloat      = 250

    let fadeAlpha: CGFloat = 0.5

    init(direction: SlideAnimationDirectionStyle) {
        self.direction = direction
        super.init()
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return TimeInterval(duration)
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        // Setup Views
        guard let presentedFromVC = transitionContext.viewController(forKey: .from) else {transitionContext.completeTransition(false); return }
        guard let presentingToVC  = transitionContext.viewController(forKey: .to)   else {transitionContext.completeTransition(false); return }
        let contrainerView = transitionContext.containerView // アニメーションはこのViewで行われる、アニメーションを実装する presenter, presenteeをこの上に載せないとアニメーションが動かない

        // Setup Frames
        let positionHidden = CGRect(x: contrainerView.frame.width + 1, y: 0, width: presentedControllerWidth, height: contrainerView.frame.height)
        let positionShown  = CGRect(x: contrainerView.frame.width - presentedControllerWidth, y: 0, width: presentedControllerWidth, height: contrainerView.frame.height)

        switch direction {

        case .slideIn:

            contrainerView.addSubview(presentingToVC.view)
            presentingToVC.view.frame = positionHidden

            UIView.animate(withDuration: duration, animations: {
                presentingToVC.view.frame = positionShown
                presentedFromVC.view.alpha = self.fadeAlpha

            }, completion: { success in
                transitionContext.completeTransition( success )
            })

        case .slideOut:

            contrainerView.addSubview(presentedFromVC.view)
            presentedFromVC.view.frame = positionShown

            UIView.animate(withDuration: duration, animations: {
                presentedFromVC.view.frame = positionHidden
                presentingToVC.view.alpha = 1.0

            }, completion: { success in
                transitionContext.completeTransition( success )

            })
        }
    }

}
Bigair
  • 1,452
  • 3
  • 15
  • 42

1 Answers1

2

Have you tried using UIGestureRecognizer yet? The UIGestureRecognizer can be utilized to recognize tap events, both inside a child view controller and a parent view controller. For swift 3, there should be a handleTapBehind function of the UIRecognizerDelegate that should allow you to do what you're looking for.

See if the what is documented here

See the "Swift 3.1 solution that works in both portrait and landscape" in the linked post.

mgwiggles
  • 141
  • 5