Hide a black fade when self.dismiss with CATransition

659 Views Asked by At

I want to make my viewController to dismiss to an old viewController with animation. But when I use CATransition my viewController and old viewController fades black. Is there any way I can make it not to fade?

let transition = CATransition()
transition.duration = 1.0
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
view.window!.layer.add(transition, forKey: kCATransition)
self.dismiss(animated: false, completion: nil)
1

There are 1 best solutions below

0
hbk On BEST ANSWER

Read more about transition here and try to modify available parameters to achieve required effects.

Good undocumented info about transition available here.

In case you want some good solution - you should prepare custom transition for your screen - check this WWDC video

Alternative fast (but not the best) solution may be manual control of presentation/dismiss in your viewController:

import UIKit

final class AnimatableViewController: UIViewController {

    private var panStartLocation:CGPoint = CGPoint.zero
    private var panPrevLocation:CGPoint = CGPoint.zero

    var onClose:(()->())?

    // MARK: - LifeCycle

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

        openAnimation()
    }

    // MARK: - IBAction

    @objc private func closeButtonAction(_ sender: UIButton) {
        dismiss(animated: true, completion: { [weak self] in
            self?.onClose?()
        })
    }

    // MARK: - Gestures

    @IBAction private func didDetectPan(_ sender: UIPanGestureRecognizer) {
        switch sender.state {
            case .began:
                panStartLocation = sender.location(in: navigationController?.view)
                panPrevLocation = panStartLocation
            case .cancelled, .ended:
                finishAnimation()
            case .changed:
                let newPoint:CGPoint = sender.location(in: navigationController?.view)
                let dy:CGFloat = newPoint.y - panPrevLocation.y
                var newPosition:CGPoint = view.center

                if (newPoint.y - panStartLocation.y > 0) {
                    newPosition.y += dy
                } else {
                    newPosition.y = self.view.bounds.height / 2
                }
                view.center = newPosition
                panPrevLocation = newPoint
            default:
                break
        }
    }

    //MARK: Animation

    private func finishAnimation() {
        let center:CGPoint = view.center
        if (center.y > self.view.bounds.height / 2 * 1.35) {
            closeAnimation()
        } else {
            openAnimation()
        }
    }

    private func closeAnimation() {
        let fullAnimTime:CGFloat = 0.5
        let endPoint:CGPoint = CGPoint(x:view.center.x, y:view.bounds.height / 2 * 3)
        let animTime:CGFloat = ((endPoint.y - view.center.y) / self.view.bounds.height) * fullAnimTime

        UIView.animate(withDuration: TimeInterval(animTime), animations: { [weak self] in
            self?.view.center = endPoint
            }, completion: { [weak self] _ in
                self?.dismiss(animated: false, completion: {
                    self?.onClose?()
                })
        })
    }

    private func openAnimation() {
        let fullAnimTime:CGFloat = 0.5
        let endPoint:CGPoint = CGPoint(x: view.center.x, y:self.view.bounds.height / 2)
        let animTime:CGFloat = ((view.center.y - endPoint.y) / (self.view.bounds.height / 2)) * fullAnimTime
        UIView.animate(withDuration: TimeInterval(animTime)) { [weak self] in
            self?.view.center = endPoint
        }
    }
}

extension AnimatableViewController: UIGestureRecognizerDelegate {
    // MARK: - UIGestureRecognizerDelegate

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer is UIPanGestureRecognizer {
            return false
        }
        return true
    }
}

In storyboard don't forget to set you segue parameters as:

enter image description here

And add panGesture to your root view or any additional pan Gesture to top most view, that can be used for pan - in my case - i just add pan to rootView:

enter image description here

Result:

enter image description here