Change RootViewcontroller with the Push Transition effect

in my iOS App i need to change the rootviewController of the window in between of app .so when i change my rootviewcontroller dyncamically its flicking the view before its change.but what i want is to give a smooth transition when rootviewcontroller is changed.

i had tried with the following but its not the transition i want.

  • Centering Modal View with Autolayout
  • UIViewanimation trantitionfromView using UIViewflip animation
  • UiView.animateWithDuration Not Animating Swift
  • Swift: Problems with custom UIView.transition?
  • How to add a slide-in view effect?
  • How to add image with parallax effect above UITableView header and keep header sticky
  • [UIView transitionWithView:self.window
                          duration:.8
                           options:UIViewAnimationOptionTransitionCurlUp
                        animations:^{
    
                            self.window.rootViewController = tabBarControllerMain;
        [self.window makeKeyAndVisible];
                        }
                        completion:NULL];
    

    i want specific transition like navigationcontroller pushview transition.

    can any body give me idea how to achieve that?

    3 Solutions Collect From Internet About “Change RootViewcontroller with the Push Transition effect”

    Based on this Apple’s documentation

    UIViewController *viewControllerToBeShown=[[UIViewController alloc]init];
    
    //viewControllerToBeShown.view.frame = self.view.frame;
    
    viewControllerToBeShown.view.backgroundColor = [UIColor orangeColor];
    
    
    
    AppDelegateClass *yourAppDelegate  =(AppDelegateClass*)[UIApplication sharedApplication].delegate;
    
    
    UIView *myView1 = yourAppDelegate.window.rootViewController.view;
    
    UIView *myView2 = viewControllerToBeShown.view;
    
    myView2.frame = yourAppDelegate.window.bounds;
    
    
    [yourAppDelegate.window addSubview:myView2];
    
    
    CATransition* transition = [CATransition animation];
    transition.startProgress = 0;
    transition.endProgress = 1.0;
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromRight;
    transition.duration = 5.0;
    
    // Add the transition animation to both layers
    [myView1.layer addAnimation:transition forKey:@"transition"];
    [myView2.layer addAnimation:transition forKey:@"transition"];
    
    myView1.hidden = YES;
    myView2.hidden = NO;
    
    
    yourAppDelegate.window.rootViewController = viewControllerToBeShown;
    

    Swift

            guard let appDelegate = UIApplication.shared.delegate,
                let appDelegateWindow = appDelegate.window,
                let appDelegateView = window.rootViewController?.view,
                let viewContollersView = viewController.view else {
                return
            }
            viewContollersView.frame = (appDelegateWindow?.bounds)!
            appDelegate.window??.addSubview(viewContollersView)
            let transition = CATransition()
            transition.startProgress = 0
            transition.endProgress = 1.0
            transition.type = kCATransitionPush
            transition.subtype = kCATransitionFromRight
            transition.duration = 0.35
            appDelegateView.layer.add(transition, forKey: "transition")
            viewContollersView.layer.add(transition, forKey: "transition")
            appDelegateView.isHidden = true
            viewContollersView.isHidden = false
            appDelegateWindow?.rootViewController = viewController
    

    Here is code in Swift for how to make Push and Pop animation in rootviewcontroller.

    //Declare enum
    enum AnimationType{
            case ANIMATE_RIGHT
            case ANIMATE_LEFT
            case ANIMATE_UP
            case ANIMATE_DOWN
        }
    // Create Function...
    
        func showViewControllerWith(newViewController:UIViewController, usingAnimation animationType:AnimationType)
    {
    
        let currentViewController = UIApplication.sharedApplication().delegate?.window??.rootViewController
        let width = currentViewController?.view.frame.size.width;
        let height = currentViewController?.view.frame.size.height;
    
        var previousFrame:CGRect?
        var nextFrame:CGRect?
    
        switch animationType
        {
            case .ANIMATE_LEFT:
                previousFrame = CGRectMake(width!-1, 0.0, width!, height!)
                nextFrame = CGRectMake(-width!, 0.0, width!, height!);
            case .ANIMATE_RIGHT:
                previousFrame = CGRectMake(-width!+1, 0.0, width!, height!);
                nextFrame = CGRectMake(width!, 0.0, width!, height!);
            case .ANIMATE_UP:
                previousFrame = CGRectMake(0.0, height!-1, width!, height!);
                nextFrame = CGRectMake(0.0, -height!+1, width!, height!);
            case .ANIMATE_DOWN:
                previousFrame = CGRectMake(0.0, -height!+1, width!, height!);
                nextFrame = CGRectMake(0.0, height!-1, width!, height!);
        }
    
        newViewController.view.frame = previousFrame!
        UIApplication.sharedApplication().delegate?.window??.addSubview(newViewController.view)
        UIView.animateWithDuration(0.33,
            animations: { () -> Void in
            newViewController.view.frame = (currentViewController?.view.frame)!
                currentViewController?.view.frame = nextFrame!
    
            })
            { (fihish:Bool) -> Void in
                UIApplication.sharedApplication().delegate?.window??.rootViewController = newViewController
            }
    }
    
    
    // call the func for ANIMATE_LEFT or ANIMATE_RIGHT etc
    
         self.showViewControllerWith(rootViewController, usingAnimation: AnimationType.ANIMATE_LEFT)
    

    Hope this helps…

    Basing on Hardik Darji’s answer I’ve created UIWindow extension to swap rootViewController with configurable animation type that simulates system animations – push, pop, present and dismiss.

    Swift 3.

    public enum SwapRootVCAnimationType {
        case push
        case pop
        case present
        case dismiss
    }
    
    
    extension UIWindow {
    public func swapRootViewControllerWithAnimation(newViewController:UIViewController, animationType:SwapRootVCAnimationType, completion: (() -> ())? = nil)
    {
        guard let currentViewController = rootViewController else {
            return
        }
    
        let width = currentViewController.view.frame.size.width;
        let height = currentViewController.view.frame.size.height;
    
        var newVCStartAnimationFrame: CGRect?
        var currentVCEndAnimationFrame:CGRect?
    
        var newVCAnimated = true
    
        switch animationType
        {
        case .push:
            newVCStartAnimationFrame = CGRect(x: width, y: 0, width: width, height: height)
            currentVCEndAnimationFrame = CGRect(x: 0 - width/4, y: 0, width: width, height: height)
        case .pop:
            currentVCEndAnimationFrame = CGRect(x: width, y: 0, width: width, height: height)
            newVCStartAnimationFrame = CGRect(x: 0 - width/4, y: 0, width: width, height: height)
            newVCAnimated = false
        case .present:
            newVCStartAnimationFrame = CGRect(x: 0, y: height, width: width, height: height)
        case .dismiss:
            currentVCEndAnimationFrame = CGRect(x: 0, y: height, width: width, height: height)
            newVCAnimated = false
        }
    
        newViewController.view.frame = newVCStartAnimationFrame ?? CGRect(x: 0, y: 0, width: width, height: height)
    
        addSubview(newViewController.view)
    
        if !newVCAnimated {
            bringSubview(toFront: currentViewController.view)
        }
    
        UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: {
            if let currentVCEndAnimationFrame = currentVCEndAnimationFrame {
                currentViewController.view.frame = currentVCEndAnimationFrame
            }
    
            newViewController.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
        }, completion: { finish in
            self.rootViewController = newViewController
            completion?()
        })
    
        makeKeyAndVisible()
    }
    

    }