RootViewController切换过渡动画

Jef*_*son 123 xcode cocoa-touch objective-c ios

有没有什么方法可以在将现有的viewcontroller替换为rootviewcontroller并使用appDelegate中的新视频时获得过渡/动画效果?

Ole*_*ann 270

您可以rootViewController在转换动画块中包装切换:

[UIView transitionWithView:self.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionFlipFromLeft
                animations:^{ self.window.rootViewController = newViewController; }
                completion:nil];
Run Code Online (Sandbox Code Playgroud)

  • 我注意到了一些问题,即错位的元素/延迟加载的元素.例如,如果现有根vc上没有导航栏,则为具有一个的新vc设置动画,动画完成,然后添加导航栏.它看起来有点傻 - 任何关于为什么会这样做的想法,以及可以做些什么? (14认同)
  • 嘿Ole,我尝试了这种方法,它部分工作,事情是我的应用程序只能保持横向模式,但通过执行rootviewcontroller转换,新呈现的视图控制器在开始时以纵向加载,并快速旋转到横向模式,怎么解决? (5认同)
  • 我在这里的单独问题中回答了Chris Chen的问题(希望!也许?):http://stackoverflow.com/questions/8053832/rootviewcontroller-animation-transition-initial-orientation-is-wrong (4认同)

Jes*_*sus 65

我找到了这个并完美地工作:

在你的appDelegate中:

- (void)changeRootViewController:(UIViewController*)viewController {

    if (!self.window.rootViewController) {
        self.window.rootViewController = viewController;
        return;
    }

    UIView *snapShot = [self.window snapshotViewAfterScreenUpdates:YES];

    [viewController.view addSubview:snapShot];

    self.window.rootViewController = viewController;

    [UIView animateWithDuration:0.5 animations:^{
        snapShot.layer.opacity = 0;
        snapShot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
    } completion:^(BOOL finished) {
        [snapShot removeFromSuperview];
    }];
}
Run Code Online (Sandbox Code Playgroud)

在你的应用程序中

 if (!app) { app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; }
        [app changeRootViewController:newViewController];
Run Code Online (Sandbox Code Playgroud)

积分:

https://gist.github.com/gimenete/53704124583b5df3b407


Nei*_*rov 39

我发布了在swift中实现的耶稣答案.它将viewcontroller的标识符作为参数,从storyboard desiredViewController加载并使用动画更改rootViewController.

Swift 3.0更新:

  func changeRootViewController(with identifier:String!) {
    let storyboard = self.window?.rootViewController?.storyboard
    let desiredViewController = storyboard?.instantiateViewController(withIdentifier: identifier);

    let snapshot:UIView = (self.window?.snapshotView(afterScreenUpdates: true))!
    desiredViewController?.view.addSubview(snapshot);

    self.window?.rootViewController = desiredViewController;

    UIView.animate(withDuration: 0.3, animations: {() in
      snapshot.layer.opacity = 0;
      snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
      }, completion: {
        (value: Bool) in
        snapshot.removeFromSuperview();
    });
  }
Run Code Online (Sandbox Code Playgroud)

Swift 2.2更新:

  func changeRootViewControllerWithIdentifier(identifier:String!) {
    let storyboard = self.window?.rootViewController?.storyboard
    let desiredViewController = storyboard?.instantiateViewControllerWithIdentifier(identifier);

    let snapshot:UIView = (self.window?.snapshotViewAfterScreenUpdates(true))!
    desiredViewController?.view.addSubview(snapshot);

    self.window?.rootViewController = desiredViewController;

    UIView.animateWithDuration(0.3, animations: {() in
      snapshot.layer.opacity = 0;
      snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
      }, completion: {
        (value: Bool) in
        snapshot.removeFromSuperview();
    });
  }

  class func sharedAppDelegate() -> AppDelegate? {
    return UIApplication.sharedApplication().delegate as? AppDelegate;
  }
Run Code Online (Sandbox Code Playgroud)

之后,您可以随时随地使用:

let appDelegate = AppDelegate.sharedAppDelegate()
appDelegate?.changeRootViewControllerWithIdentifier("YourViewControllerID")
Run Code Online (Sandbox Code Playgroud)

Swift 3.0更新

let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.changeRootViewController(with: "listenViewController")
Run Code Online (Sandbox Code Playgroud)


小智 22

//在swift中:

UIView.transitionWithView(self.window!, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromLeft, animations: {
  self.window?.rootViewController = anyViewController
}, completion: nil)
Run Code Online (Sandbox Code Playgroud)


Dmi*_*rov 10

试试吧.对我来说很好.

BOOL oldState = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
self.window.rootViewController = viewController;
[UIView transitionWithView:self.window duration:0.5 options:transition animations:^{
    //
} completion:^(BOOL finished) {
    [UIView setAnimationsEnabled:oldState];
}];
Run Code Online (Sandbox Code Playgroud)

编辑:

这个更好.

- (void)setRootViewController:(UIViewController *)viewController
               withTransition:(UIViewAnimationOptions)transition
                   completion:(void (^)(BOOL finished))completion {
    UIViewController *oldViewController = self.window.rootViewController;
    [UIView transitionFromView:oldViewController.view 
                        toView:viewController.view
                      duration:0.5f
                       options:(UIViewAnimationOptions)(transition|UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionLayoutSubviews)
                    completion:^(BOOL finished) {
        self.window.rootViewController = viewController;
        if (completion) {
            completion(finished);
        }
    }];
}
Run Code Online (Sandbox Code Playgroud)