How to solve this problem with custom transition in iOS?











up vote
3
down vote

favorite












I built a class to implement a circular transition between view controllers. When I hit the button to navigate to the other view controller a circle starts growing from the button until it fills the screen with the new controller. When I dismiss the view controller I expected this circle to shrink down back to the original position. It's also working. The only problem is that when the dismiss is underway the back of the screen while the circle is shrinking is completely black and after the animation is completed the new viewController appears abruptly.



Here are some photos of the effect:



enter image description here



Here's the code of the custom class:



class customTransition: NSObject, UIViewControllerAnimatedTransitioning{

var duration: TimeInterval = 0.5
var startPoint = CGPoint.zero

var circle = UIView()

var circleColor = UIColor.white
enum transitMode: Int {
case presenting, dismissing
}

var transitionMode: transitMode = .presenting

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

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

let container = transitionContext.containerView
guard let to = transitionContext.view(forKey: UITransitionContextViewKey.to) else {return}
guard let from = transitionContext.view(forKey: UITransitionContextViewKey.from) else {return}

circleColor = to.backgroundColor ?? UIColor.white

if transitionMode == .presenting {
to.translatesAutoresizingMaskIntoConstraints = false
to.center = startPoint

circle = UIView()
circle.backgroundColor = circleColor
circle.frame = getFrameForCircle(rect: to.frame)
circle.layer.cornerRadius = circle.frame.width / 2
circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
circle.alpha = 0


circle.addSubview(to)

to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

container.addSubview(circle)

UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = from.center
self.circle.transform = CGAffineTransform.identity
self.circle.alpha = 1

}) { (sucess) in

transitionContext.completeTransition(sucess)

}

} else if transitionMode == .dismissing {


UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = self.startPoint
self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
self.circle.alpha = 0

}) { (sucess) in
transitionContext.completeTransition(sucess)
}
}
}




func getFrameForCircle(rect: CGRect) -> CGRect{
let width = Float(rect.width)
let height = Float(rect.height)

let diameter = CGFloat(sqrtf(width * width + height * height))

let x: CGFloat = rect.midX - (diameter / 2)
let y: CGFloat = rect.midY - (diameter / 2)

return CGRect(x: x, y: y, width: diameter, height: diameter)
}



}


and the implementation...



    let circularTransition = customTransition()


the call for the present view controller... I tried to set secondVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext but when I set this line it ignores completely the animation transition I don't know why...
`



 @objc func handlePresent(sender: UIButton){
let secondVC = nextVC()
secondVC.transitioningDelegate = self
present(secondVC, animated: true, completion: nil)

}


delegate methods:



  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.startPoint = presentButton.center
circularTransition.transitionMode = .presenting
return circularTransition
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.transitionMode = .dismissing
circularTransition.startPoint = presentButton.center

return circularTransition
}


What am I missing here? Any suggestions?
No storyboard being used, just code.










share|improve this question
























  • I think you're seeing this problem because you're using present and not a navigationController. I recommend trying to use a navigationController to push/pop ViewController and applying your animation when that ViewController is presented. So you would push/pop VC from the NavController without an animation. However, the VC itself would apply your desired animation when appearing either shrinking or growing to/from a circle
    – DoesData
    Nov 17 at 22:15










  • You show code that displays the 2nd controller over the 1st. Please also add how you dismiss the 2nd and attempt to transition back to the 1st.
    – rmaddy
    Nov 17 at 22:21















up vote
3
down vote

favorite












I built a class to implement a circular transition between view controllers. When I hit the button to navigate to the other view controller a circle starts growing from the button until it fills the screen with the new controller. When I dismiss the view controller I expected this circle to shrink down back to the original position. It's also working. The only problem is that when the dismiss is underway the back of the screen while the circle is shrinking is completely black and after the animation is completed the new viewController appears abruptly.



Here are some photos of the effect:



enter image description here



Here's the code of the custom class:



class customTransition: NSObject, UIViewControllerAnimatedTransitioning{

var duration: TimeInterval = 0.5
var startPoint = CGPoint.zero

var circle = UIView()

var circleColor = UIColor.white
enum transitMode: Int {
case presenting, dismissing
}

var transitionMode: transitMode = .presenting

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

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

let container = transitionContext.containerView
guard let to = transitionContext.view(forKey: UITransitionContextViewKey.to) else {return}
guard let from = transitionContext.view(forKey: UITransitionContextViewKey.from) else {return}

circleColor = to.backgroundColor ?? UIColor.white

if transitionMode == .presenting {
to.translatesAutoresizingMaskIntoConstraints = false
to.center = startPoint

circle = UIView()
circle.backgroundColor = circleColor
circle.frame = getFrameForCircle(rect: to.frame)
circle.layer.cornerRadius = circle.frame.width / 2
circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
circle.alpha = 0


circle.addSubview(to)

to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

container.addSubview(circle)

UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = from.center
self.circle.transform = CGAffineTransform.identity
self.circle.alpha = 1

}) { (sucess) in

transitionContext.completeTransition(sucess)

}

} else if transitionMode == .dismissing {


UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = self.startPoint
self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
self.circle.alpha = 0

}) { (sucess) in
transitionContext.completeTransition(sucess)
}
}
}




func getFrameForCircle(rect: CGRect) -> CGRect{
let width = Float(rect.width)
let height = Float(rect.height)

let diameter = CGFloat(sqrtf(width * width + height * height))

let x: CGFloat = rect.midX - (diameter / 2)
let y: CGFloat = rect.midY - (diameter / 2)

return CGRect(x: x, y: y, width: diameter, height: diameter)
}



}


and the implementation...



    let circularTransition = customTransition()


the call for the present view controller... I tried to set secondVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext but when I set this line it ignores completely the animation transition I don't know why...
`



 @objc func handlePresent(sender: UIButton){
let secondVC = nextVC()
secondVC.transitioningDelegate = self
present(secondVC, animated: true, completion: nil)

}


delegate methods:



  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.startPoint = presentButton.center
circularTransition.transitionMode = .presenting
return circularTransition
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.transitionMode = .dismissing
circularTransition.startPoint = presentButton.center

return circularTransition
}


What am I missing here? Any suggestions?
No storyboard being used, just code.










share|improve this question
























  • I think you're seeing this problem because you're using present and not a navigationController. I recommend trying to use a navigationController to push/pop ViewController and applying your animation when that ViewController is presented. So you would push/pop VC from the NavController without an animation. However, the VC itself would apply your desired animation when appearing either shrinking or growing to/from a circle
    – DoesData
    Nov 17 at 22:15










  • You show code that displays the 2nd controller over the 1st. Please also add how you dismiss the 2nd and attempt to transition back to the 1st.
    – rmaddy
    Nov 17 at 22:21













up vote
3
down vote

favorite









up vote
3
down vote

favorite











I built a class to implement a circular transition between view controllers. When I hit the button to navigate to the other view controller a circle starts growing from the button until it fills the screen with the new controller. When I dismiss the view controller I expected this circle to shrink down back to the original position. It's also working. The only problem is that when the dismiss is underway the back of the screen while the circle is shrinking is completely black and after the animation is completed the new viewController appears abruptly.



Here are some photos of the effect:



enter image description here



Here's the code of the custom class:



class customTransition: NSObject, UIViewControllerAnimatedTransitioning{

var duration: TimeInterval = 0.5
var startPoint = CGPoint.zero

var circle = UIView()

var circleColor = UIColor.white
enum transitMode: Int {
case presenting, dismissing
}

var transitionMode: transitMode = .presenting

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

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

let container = transitionContext.containerView
guard let to = transitionContext.view(forKey: UITransitionContextViewKey.to) else {return}
guard let from = transitionContext.view(forKey: UITransitionContextViewKey.from) else {return}

circleColor = to.backgroundColor ?? UIColor.white

if transitionMode == .presenting {
to.translatesAutoresizingMaskIntoConstraints = false
to.center = startPoint

circle = UIView()
circle.backgroundColor = circleColor
circle.frame = getFrameForCircle(rect: to.frame)
circle.layer.cornerRadius = circle.frame.width / 2
circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
circle.alpha = 0


circle.addSubview(to)

to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

container.addSubview(circle)

UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = from.center
self.circle.transform = CGAffineTransform.identity
self.circle.alpha = 1

}) { (sucess) in

transitionContext.completeTransition(sucess)

}

} else if transitionMode == .dismissing {


UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = self.startPoint
self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
self.circle.alpha = 0

}) { (sucess) in
transitionContext.completeTransition(sucess)
}
}
}




func getFrameForCircle(rect: CGRect) -> CGRect{
let width = Float(rect.width)
let height = Float(rect.height)

let diameter = CGFloat(sqrtf(width * width + height * height))

let x: CGFloat = rect.midX - (diameter / 2)
let y: CGFloat = rect.midY - (diameter / 2)

return CGRect(x: x, y: y, width: diameter, height: diameter)
}



}


and the implementation...



    let circularTransition = customTransition()


the call for the present view controller... I tried to set secondVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext but when I set this line it ignores completely the animation transition I don't know why...
`



 @objc func handlePresent(sender: UIButton){
let secondVC = nextVC()
secondVC.transitioningDelegate = self
present(secondVC, animated: true, completion: nil)

}


delegate methods:



  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.startPoint = presentButton.center
circularTransition.transitionMode = .presenting
return circularTransition
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.transitionMode = .dismissing
circularTransition.startPoint = presentButton.center

return circularTransition
}


What am I missing here? Any suggestions?
No storyboard being used, just code.










share|improve this question















I built a class to implement a circular transition between view controllers. When I hit the button to navigate to the other view controller a circle starts growing from the button until it fills the screen with the new controller. When I dismiss the view controller I expected this circle to shrink down back to the original position. It's also working. The only problem is that when the dismiss is underway the back of the screen while the circle is shrinking is completely black and after the animation is completed the new viewController appears abruptly.



Here are some photos of the effect:



enter image description here



Here's the code of the custom class:



class customTransition: NSObject, UIViewControllerAnimatedTransitioning{

var duration: TimeInterval = 0.5
var startPoint = CGPoint.zero

var circle = UIView()

var circleColor = UIColor.white
enum transitMode: Int {
case presenting, dismissing
}

var transitionMode: transitMode = .presenting

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

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

let container = transitionContext.containerView
guard let to = transitionContext.view(forKey: UITransitionContextViewKey.to) else {return}
guard let from = transitionContext.view(forKey: UITransitionContextViewKey.from) else {return}

circleColor = to.backgroundColor ?? UIColor.white

if transitionMode == .presenting {
to.translatesAutoresizingMaskIntoConstraints = false
to.center = startPoint

circle = UIView()
circle.backgroundColor = circleColor
circle.frame = getFrameForCircle(rect: to.frame)
circle.layer.cornerRadius = circle.frame.width / 2
circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
circle.alpha = 0


circle.addSubview(to)

to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

container.addSubview(circle)

UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = from.center
self.circle.transform = CGAffineTransform.identity
self.circle.alpha = 1

}) { (sucess) in

transitionContext.completeTransition(sucess)

}

} else if transitionMode == .dismissing {


UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = self.startPoint
self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
self.circle.alpha = 0

}) { (sucess) in
transitionContext.completeTransition(sucess)
}
}
}




func getFrameForCircle(rect: CGRect) -> CGRect{
let width = Float(rect.width)
let height = Float(rect.height)

let diameter = CGFloat(sqrtf(width * width + height * height))

let x: CGFloat = rect.midX - (diameter / 2)
let y: CGFloat = rect.midY - (diameter / 2)

return CGRect(x: x, y: y, width: diameter, height: diameter)
}



}


and the implementation...



    let circularTransition = customTransition()


the call for the present view controller... I tried to set secondVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext but when I set this line it ignores completely the animation transition I don't know why...
`



 @objc func handlePresent(sender: UIButton){
let secondVC = nextVC()
secondVC.transitioningDelegate = self
present(secondVC, animated: true, completion: nil)

}


delegate methods:



  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.startPoint = presentButton.center
circularTransition.transitionMode = .presenting
return circularTransition
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.transitionMode = .dismissing
circularTransition.startPoint = presentButton.center

return circularTransition
}


What am I missing here? Any suggestions?
No storyboard being used, just code.







ios swift uiviewanimationtransition






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 17 at 22:21









rmaddy

235k27306373




235k27306373










asked Nov 17 at 21:55









Lucas

875




875












  • I think you're seeing this problem because you're using present and not a navigationController. I recommend trying to use a navigationController to push/pop ViewController and applying your animation when that ViewController is presented. So you would push/pop VC from the NavController without an animation. However, the VC itself would apply your desired animation when appearing either shrinking or growing to/from a circle
    – DoesData
    Nov 17 at 22:15










  • You show code that displays the 2nd controller over the 1st. Please also add how you dismiss the 2nd and attempt to transition back to the 1st.
    – rmaddy
    Nov 17 at 22:21


















  • I think you're seeing this problem because you're using present and not a navigationController. I recommend trying to use a navigationController to push/pop ViewController and applying your animation when that ViewController is presented. So you would push/pop VC from the NavController without an animation. However, the VC itself would apply your desired animation when appearing either shrinking or growing to/from a circle
    – DoesData
    Nov 17 at 22:15










  • You show code that displays the 2nd controller over the 1st. Please also add how you dismiss the 2nd and attempt to transition back to the 1st.
    – rmaddy
    Nov 17 at 22:21
















I think you're seeing this problem because you're using present and not a navigationController. I recommend trying to use a navigationController to push/pop ViewController and applying your animation when that ViewController is presented. So you would push/pop VC from the NavController without an animation. However, the VC itself would apply your desired animation when appearing either shrinking or growing to/from a circle
– DoesData
Nov 17 at 22:15




I think you're seeing this problem because you're using present and not a navigationController. I recommend trying to use a navigationController to push/pop ViewController and applying your animation when that ViewController is presented. So you would push/pop VC from the NavController without an animation. However, the VC itself would apply your desired animation when appearing either shrinking or growing to/from a circle
– DoesData
Nov 17 at 22:15












You show code that displays the 2nd controller over the 1st. Please also add how you dismiss the 2nd and attempt to transition back to the 1st.
– rmaddy
Nov 17 at 22:21




You show code that displays the 2nd controller over the 1st. Please also add how you dismiss the 2nd and attempt to transition back to the 1st.
– rmaddy
Nov 17 at 22:21












1 Answer
1






active

oldest

votes

















up vote
0
down vote













If you don't use navigationController, it's necessary to use the .custom mode in the presentedviewController.



 import UIKit

class TransViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
}
let circularTransition = customTransition()

@IBOutlet var presentButton : UIButton!

@IBAction func handlePresent(sender: UIButton){

if let secondVC = storyboard?.instantiateViewController(withIdentifier: "next"){
secondVC.modalPresentationStyle = .custom
secondVC.transitioningDelegate = self
present(secondVC, animated: true, completion: nil)
}
}

}


class BackViewController: UIViewController {

@IBAction func dismissMe(sender: UIButton){
self.dismiss(animated: true, completion: nil)
}

}

extension TransViewController: UIViewControllerTransitioningDelegate {

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

circularTransition.startPoint = presentButton.center
circularTransition.transitionMode = .presenting
return circularTransition
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
circularTransition.transitionMode = .dismissing
circularTransition.startPoint = presentButton.center

return circularTransition
}

}


If there is no from or to view, we have use the from and to view from containView.



   func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

let container = transitionContext.containerView
var to : UIView!
var from : UIView!
to = transitionContext.view(forKey: UITransitionContextViewKey.to)
if to == nil {to = container}
from = transitionContext.view(forKey: UITransitionContextViewKey.from)
if from == nil {from = container}


The rest is same:



 circleColor = to.backgroundColor ?? UIColor.white

if transitionMode == .presenting {
to.translatesAutoresizingMaskIntoConstraints = false
to.center = startPoint

circle = UIView()
circle.backgroundColor = circleColor
circle.frame = getFrameForCircle(rect: to.frame)
circle.layer.cornerRadius = circle.frame.width / 2
circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
circle.alpha = 0


circle.addSubview(to)

to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

container.addSubview(circle)

UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = from.center
self.circle.transform = CGAffineTransform.identity
self.circle.alpha = 1

}) { (sucess) in

transitionContext.completeTransition(sucess)

}

} else if transitionMode == .dismissing {


UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.circle.center = self.startPoint
self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
self.circle.alpha = 0

}) { (sucess) in
transitionContext.completeTransition(sucess)
}
}
}





share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53355915%2fhow-to-solve-this-problem-with-custom-transition-in-ios%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    If you don't use navigationController, it's necessary to use the .custom mode in the presentedviewController.



     import UIKit

    class TransViewController: UIViewController {

    override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    }
    let circularTransition = customTransition()

    @IBOutlet var presentButton : UIButton!

    @IBAction func handlePresent(sender: UIButton){

    if let secondVC = storyboard?.instantiateViewController(withIdentifier: "next"){
    secondVC.modalPresentationStyle = .custom
    secondVC.transitioningDelegate = self
    present(secondVC, animated: true, completion: nil)
    }
    }

    }


    class BackViewController: UIViewController {

    @IBAction func dismissMe(sender: UIButton){
    self.dismiss(animated: true, completion: nil)
    }

    }

    extension TransViewController: UIViewControllerTransitioningDelegate {

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

    circularTransition.startPoint = presentButton.center
    circularTransition.transitionMode = .presenting
    return circularTransition
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    circularTransition.transitionMode = .dismissing
    circularTransition.startPoint = presentButton.center

    return circularTransition
    }

    }


    If there is no from or to view, we have use the from and to view from containView.



       func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    let container = transitionContext.containerView
    var to : UIView!
    var from : UIView!
    to = transitionContext.view(forKey: UITransitionContextViewKey.to)
    if to == nil {to = container}
    from = transitionContext.view(forKey: UITransitionContextViewKey.from)
    if from == nil {from = container}


    The rest is same:



     circleColor = to.backgroundColor ?? UIColor.white

    if transitionMode == .presenting {
    to.translatesAutoresizingMaskIntoConstraints = false
    to.center = startPoint

    circle = UIView()
    circle.backgroundColor = circleColor
    circle.frame = getFrameForCircle(rect: to.frame)
    circle.layer.cornerRadius = circle.frame.width / 2
    circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
    circle.alpha = 0


    circle.addSubview(to)

    to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
    to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
    to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
    to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

    container.addSubview(circle)

    UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
    self.circle.center = from.center
    self.circle.transform = CGAffineTransform.identity
    self.circle.alpha = 1

    }) { (sucess) in

    transitionContext.completeTransition(sucess)

    }

    } else if transitionMode == .dismissing {


    UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
    self.circle.center = self.startPoint
    self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
    self.circle.alpha = 0

    }) { (sucess) in
    transitionContext.completeTransition(sucess)
    }
    }
    }





    share|improve this answer

























      up vote
      0
      down vote













      If you don't use navigationController, it's necessary to use the .custom mode in the presentedviewController.



       import UIKit

      class TransViewController: UIViewController {

      override func viewDidLoad() {
      super.viewDidLoad()

      // Do any additional setup after loading the view.
      }
      let circularTransition = customTransition()

      @IBOutlet var presentButton : UIButton!

      @IBAction func handlePresent(sender: UIButton){

      if let secondVC = storyboard?.instantiateViewController(withIdentifier: "next"){
      secondVC.modalPresentationStyle = .custom
      secondVC.transitioningDelegate = self
      present(secondVC, animated: true, completion: nil)
      }
      }

      }


      class BackViewController: UIViewController {

      @IBAction func dismissMe(sender: UIButton){
      self.dismiss(animated: true, completion: nil)
      }

      }

      extension TransViewController: UIViewControllerTransitioningDelegate {

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

      circularTransition.startPoint = presentButton.center
      circularTransition.transitionMode = .presenting
      return circularTransition
      }

      func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      circularTransition.transitionMode = .dismissing
      circularTransition.startPoint = presentButton.center

      return circularTransition
      }

      }


      If there is no from or to view, we have use the from and to view from containView.



         func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

      let container = transitionContext.containerView
      var to : UIView!
      var from : UIView!
      to = transitionContext.view(forKey: UITransitionContextViewKey.to)
      if to == nil {to = container}
      from = transitionContext.view(forKey: UITransitionContextViewKey.from)
      if from == nil {from = container}


      The rest is same:



       circleColor = to.backgroundColor ?? UIColor.white

      if transitionMode == .presenting {
      to.translatesAutoresizingMaskIntoConstraints = false
      to.center = startPoint

      circle = UIView()
      circle.backgroundColor = circleColor
      circle.frame = getFrameForCircle(rect: to.frame)
      circle.layer.cornerRadius = circle.frame.width / 2
      circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
      circle.alpha = 0


      circle.addSubview(to)

      to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
      to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
      to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
      to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

      container.addSubview(circle)

      UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
      self.circle.center = from.center
      self.circle.transform = CGAffineTransform.identity
      self.circle.alpha = 1

      }) { (sucess) in

      transitionContext.completeTransition(sucess)

      }

      } else if transitionMode == .dismissing {


      UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
      self.circle.center = self.startPoint
      self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
      self.circle.alpha = 0

      }) { (sucess) in
      transitionContext.completeTransition(sucess)
      }
      }
      }





      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        If you don't use navigationController, it's necessary to use the .custom mode in the presentedviewController.



         import UIKit

        class TransViewController: UIViewController {

        override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        }
        let circularTransition = customTransition()

        @IBOutlet var presentButton : UIButton!

        @IBAction func handlePresent(sender: UIButton){

        if let secondVC = storyboard?.instantiateViewController(withIdentifier: "next"){
        secondVC.modalPresentationStyle = .custom
        secondVC.transitioningDelegate = self
        present(secondVC, animated: true, completion: nil)
        }
        }

        }


        class BackViewController: UIViewController {

        @IBAction func dismissMe(sender: UIButton){
        self.dismiss(animated: true, completion: nil)
        }

        }

        extension TransViewController: UIViewControllerTransitioningDelegate {

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

        circularTransition.startPoint = presentButton.center
        circularTransition.transitionMode = .presenting
        return circularTransition
        }

        func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        circularTransition.transitionMode = .dismissing
        circularTransition.startPoint = presentButton.center

        return circularTransition
        }

        }


        If there is no from or to view, we have use the from and to view from containView.



           func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        let container = transitionContext.containerView
        var to : UIView!
        var from : UIView!
        to = transitionContext.view(forKey: UITransitionContextViewKey.to)
        if to == nil {to = container}
        from = transitionContext.view(forKey: UITransitionContextViewKey.from)
        if from == nil {from = container}


        The rest is same:



         circleColor = to.backgroundColor ?? UIColor.white

        if transitionMode == .presenting {
        to.translatesAutoresizingMaskIntoConstraints = false
        to.center = startPoint

        circle = UIView()
        circle.backgroundColor = circleColor
        circle.frame = getFrameForCircle(rect: to.frame)
        circle.layer.cornerRadius = circle.frame.width / 2
        circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
        circle.alpha = 0


        circle.addSubview(to)

        to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
        to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
        to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
        to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

        container.addSubview(circle)

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
        self.circle.center = from.center
        self.circle.transform = CGAffineTransform.identity
        self.circle.alpha = 1

        }) { (sucess) in

        transitionContext.completeTransition(sucess)

        }

        } else if transitionMode == .dismissing {


        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
        self.circle.center = self.startPoint
        self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
        self.circle.alpha = 0

        }) { (sucess) in
        transitionContext.completeTransition(sucess)
        }
        }
        }





        share|improve this answer












        If you don't use navigationController, it's necessary to use the .custom mode in the presentedviewController.



         import UIKit

        class TransViewController: UIViewController {

        override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        }
        let circularTransition = customTransition()

        @IBOutlet var presentButton : UIButton!

        @IBAction func handlePresent(sender: UIButton){

        if let secondVC = storyboard?.instantiateViewController(withIdentifier: "next"){
        secondVC.modalPresentationStyle = .custom
        secondVC.transitioningDelegate = self
        present(secondVC, animated: true, completion: nil)
        }
        }

        }


        class BackViewController: UIViewController {

        @IBAction func dismissMe(sender: UIButton){
        self.dismiss(animated: true, completion: nil)
        }

        }

        extension TransViewController: UIViewControllerTransitioningDelegate {

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

        circularTransition.startPoint = presentButton.center
        circularTransition.transitionMode = .presenting
        return circularTransition
        }

        func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        circularTransition.transitionMode = .dismissing
        circularTransition.startPoint = presentButton.center

        return circularTransition
        }

        }


        If there is no from or to view, we have use the from and to view from containView.



           func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        let container = transitionContext.containerView
        var to : UIView!
        var from : UIView!
        to = transitionContext.view(forKey: UITransitionContextViewKey.to)
        if to == nil {to = container}
        from = transitionContext.view(forKey: UITransitionContextViewKey.from)
        if from == nil {from = container}


        The rest is same:



         circleColor = to.backgroundColor ?? UIColor.white

        if transitionMode == .presenting {
        to.translatesAutoresizingMaskIntoConstraints = false
        to.center = startPoint

        circle = UIView()
        circle.backgroundColor = circleColor
        circle.frame = getFrameForCircle(rect: to.frame)
        circle.layer.cornerRadius = circle.frame.width / 2
        circle.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
        circle.alpha = 0


        circle.addSubview(to)

        to.centerXAnchor.constraint(equalTo: circle.centerXAnchor).isActive = true
        to.centerYAnchor.constraint(equalTo: circle.centerYAnchor).isActive = true
        to.widthAnchor.constraint(equalToConstant: to.frame.width).isActive = true
        to.heightAnchor.constraint(equalToConstant: to.frame.height).isActive = true

        container.addSubview(circle)

        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
        self.circle.center = from.center
        self.circle.transform = CGAffineTransform.identity
        self.circle.alpha = 1

        }) { (sucess) in

        transitionContext.completeTransition(sucess)

        }

        } else if transitionMode == .dismissing {


        UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIView.AnimationOptions.curveLinear, animations: {
        self.circle.center = self.startPoint
        self.circle.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
        self.circle.alpha = 0

        }) { (sucess) in
        transitionContext.completeTransition(sucess)
        }
        }
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 18 at 3:13









        E.Coms

        1,3951412




        1,3951412






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53355915%2fhow-to-solve-this-problem-with-custom-transition-in-ios%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

            Alcedinidae

            Origin of the phrase “under your belt”?