Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c RootViewController开关转换动画_Objective C_Ios_Xcode_Cocoa Touch - Fatal编程技术网

Objective c RootViewController开关转换动画

Objective c RootViewController开关转换动画,objective-c,ios,xcode,cocoa-touch,Objective C,Ios,Xcode,Cocoa Touch,在appDelegate中将现有的viewcontroller替换为新的rootviewcontroller时,有没有办法产生转换/动画效果?您可以将rootviewcontroller的切换包装在转换动画块中: [UIView transitionWithView:self.window duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft

在appDelegate中将现有的viewcontroller替换为新的rootviewcontroller时,有没有办法产生转换/动画效果?

您可以将
rootviewcontroller的切换包装在转换动画块中:

[UIView transitionWithView:self.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionFlipFromLeft
                animations:^{ self.window.rootViewController = newViewController; }
                completion:nil];
在AppDelegate.h中:

#define ApplicationDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)]
在控制器中:

[UIView transitionWithView:self.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionFlipFromLeft
                animations:^{
    ApplicationDelegate.window.rootViewController = newViewController;
    }
                completion:nil];

试试这个。对我来说很好

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];
}];
编辑:

这个更好

- (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);
        }
    }];
}

我发现了这一点,并且非常有效:

在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];
    }];
}
在你的应用程序中

 if (!app) { app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; }
        [app changeRootViewController:newViewController];
学分:


Swift 2

UIView.transitionWithView(self.window!, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromLeft, animations: {
  self.window?.rootViewController = anyViewController
}, completion: nil)
Swift 3、4、5

UIView.transition(with: self.window!, duration: 0.5, options: UIView.AnimationOptions.transitionFlipFromLeft, animations: {
  self.window?.rootViewController = anyViewController
}, completion: nil)

为了避免以后在应用程序中出现过渡翻转问题,最好从堆栈中清除旧视图

UIViewController *oldController=self.window.rootViewController;

[UIView transitionWithView:self.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{ self.window.rootViewController = nav; }
                completion:^(BOOL finished) {
                    if(oldController!=nil)
                        [oldController.view removeFromSuperview];
                }];

我正在用swift发布耶稣的回答。它将viewcontroller的标识符作为参数,从情节提要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();
    });
  }
  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;
  }
Swift 2.2更新:

  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();
    });
  }
  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;
  }
之后,您可以在任何地方使用非常简单的方法:

let appDelegate = AppDelegate.sharedAppDelegate()
appDelegate?.changeRootViewControllerWithIdentifier("YourViewControllerID")
Swift 3.0更新

let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.changeRootViewController(with: "listenViewController")

正确答案是不需要更换窗口上的
rootViewController
。相反,创建一个自定义的
UIViewController
,分配它一次,让它一次显示一个子控制器,并在需要时用动画替换它。您可以使用以下代码作为起点:

Swift 3.0

您使用它的方式是:

...
let rootController = FrameViewController()
rootController.display(UINavigationController(rootViewController: MyController()))
window.rootViewController = rootController
window.makeKeyAndVisible()
...

上面的示例演示了您可以将
UINavigationController
嵌套在
FrameViewController
中,并且工作正常。这种方法为您提供了高水平的定制和控制。只要调用
FrameViewController.display()
,只要您想在窗口上替换根控制器,它就会为您完成这项工作。

这是对swift 3的更新,此方法应该在您的应用程序委托中,您可以通过应用程序委托的共享实例从任何视图控制器调用它

func logOutAnimation() {
    let storyBoard = UIStoryboard.init(name: "SignIn", bundle: nil)
    let viewController = storyBoard.instantiateViewController(withIdentifier: "signInVC")
    UIView.transition(with: self.window!, duration: 0.5, options: UIViewAnimationOptions.transitionFlipFromLeft, animations: {
        self.window?.rootViewController = viewController
        self.window?.makeKeyAndVisible()
    }, completion: nil)
}
上面各种问题中缺少的部分是

    self.window?.makeKeyAndVisible()

希望这能帮助到别人。

我提出了我的方法,它在我的项目中运行良好,并且为我提供了很好的动画效果。我已经测试了在这篇文章中找到的其他建议,但其中一些没有像预期的那样起作用

- (void)transitionToViewController:(UIViewController *)viewController withTransition:(UIViewAnimationOptions)transition completion:(void (^)(BOOL finished))completion {
// Reset new RootViewController to be sure that it have not presented any controllers
[viewController dismissViewControllerAnimated:NO completion:nil];

[UIView transitionWithView:self.window
                  duration:0.5f
                   options:transition
                animations:^{
                    for (UIView *view in self.window.subviews) {
                        [view removeFromSuperview];
                    }
                    [self.window addSubview:viewController.view];

                    self.window.rootViewController = viewController;
                } completion:completion];
}
漂亮甜美的动画(使用Swift 4.x进行测试):

打电话给

guard let delegate = UIApplication.shared.delegate as? AppDelegate else { return }
delegate.present(viewController: UIViewController())

嘿,Ole,我尝试了这种方法,它部分起作用了,问题是我的应用程序只能停留在横向模式,但通过执行rootviewcontroller转换,新显示的视图控制器在开始时以纵向方式加载,并快速旋转到横向模式,如何解决?我回答了Chris Chen的问题(希望!可能?)在他的另一个问题中:嘿,我想要在同一个动画中进行推送转换,我能实现吗?我注意到了一些问题,即元素错位/延迟加载。例如,如果现有根vc上没有导航栏,则将动画设置为具有导航栏的新vc,动画完成,然后添加导航栏。看起来有点傻-有没有想过为什么会这样,以及可以做什么?我发现在动画块修复延迟加载元素的问题之前调用
newViewController.view.layoutifneed()
。这与公认的答案相同,只是格式错误。何必麻烦呢?这并不取决于您是否在视图或ViewController中。最大的区别在于,在视图和视图控制器的厚度和厚度方面,更具哲理性。这是否支持自动屏幕旋转?在我的案例中,此解决方案效果更好。使用transitionWithView时,新的根视图控制器已正确布局,直到转换完成。这种方法允许将新的根视图控制器添加到窗口中,进行布局,然后进行转换。@Wingzero稍微晚了一点,但是,这将允许任何类型的转换,无论是通过UIView.animations(例如,带有旋转的CGAffineTransform)还是自定义动画。在切换根VC时,我有一个奇怪的默认动画。第一个版本为我去掉了它。第二个版本将为子视图布局设置动画,如juhan_h所述。如果不需要,请尝试删除
UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionLayoutSubviews
,或者使用第一个版本,或者使用其他方法。XCode修复了我的代码,如下所示:```UIView.transition(带:self.view.window!,持续时间:0.5,选项:UIViewAnimationOptions.transitionFlipFromTop,动画:{appDelegate.window?.rootViewController=myViewController},完成:无)```