Jawaban:
Anda dapat membungkus pengalihan rootViewController
dalam blok animasi transisi:
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ self.window.rootViewController = newViewController; }
completion:nil];
newViewController.view.layoutIfNeeded()
sebelum blok animasi memperbaiki masalah dengan elemen-elemen malas.
Saya menemukan ini dan bekerja dengan sempurna:
di appDelegate Anda:
- (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];
}];
}
di aplikasi Anda
if (!app) { app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; }
[app changeRootViewController:newViewController];
kredit:
Saya memposting jawaban Yesus diimplementasikan dengan cepat. Dibutuhkan pengidentifikasi viewcontroller sebagai argumen, memuat dari storyboard yang diinginkanViewController dan mengubah rootViewController dengan animasi.
Pembaruan 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();
});
}
Pembaruan 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;
}
Setelah itu, Anda memiliki penggunaan yang sangat sederhana dari mana saja:
let appDelegate = AppDelegate.sharedAppDelegate()
appDelegate?.changeRootViewControllerWithIdentifier("YourViewControllerID")
Pembaruan Swift 3.0
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.changeRootViewController(with: "listenViewController")
Cepat 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)
coba saja ini. Bekerja dengan baik untuk saya.
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];
}];
EDIT:
Yang ini lebih baik.
- (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);
}
}];
}
UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionLayoutSubviews
, atau menggunakan versi pertama, atau metode lain.
Agar tidak memiliki masalah dengan flip transisi nanti di aplikasi ini baik untuk menghapus tampilan lama dari tumpukan juga
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];
}];
Jawaban yang benar adalah Anda tidak perlu mengganti rootViewController
di jendela Anda. Alih-alih, buat custom UIViewController
, tetapkan sekali dan biarkan menampilkan satu pengontrol anak sekaligus dan ganti dengan animasi jika diperlukan. Anda dapat menggunakan potongan kode berikut sebagai titik awal:
Swift 3.0
import Foundation
import UIKit
/// Displays a single child controller at a time.
/// Replaces the current child controller optionally with animation.
class FrameViewController: UIViewController {
private(set) var displayedViewController: UIViewController?
func display(_ viewController: UIViewController, animated: Bool = false) {
addChildViewController(viewController)
let oldViewController = displayedViewController
view.addSubview(viewController.view)
viewController.view.layoutIfNeeded()
let finishDisplay: (Bool) -> Void = {
[weak self] finished in
if !finished { return }
oldViewController?.view.removeFromSuperview()
oldViewController?.removeFromParentViewController()
viewController.didMove(toParentViewController: self)
}
if (animated) {
viewController.view.alpha = 0
UIView.animate(
withDuration: 0.5,
animations: { viewController.view.alpha = 1; oldViewController?.view.alpha = 0 },
completion: finishDisplay
)
}
else {
finishDisplay(true)
}
displayedViewController = viewController
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return displayedViewController?.preferredStatusBarStyle ?? .default
}
}
Dan cara Anda menggunakannya adalah:
...
let rootController = FrameViewController()
rootController.display(UINavigationController(rootViewController: MyController()))
window.rootViewController = rootController
window.makeKeyAndVisible()
...
Contoh di atas menunjukkan bahwa Anda dapat bersarang UINavigationController
di dalam FrameViewController
dan berfungsi dengan baik. Pendekatan ini memberi Anda tingkat kustomisasi dan kontrol yang tinggi. Hubungi FrameViewController.display(_)
saja kapan saja Anda ingin mengganti pengendali root di jendela Anda, dan itu akan melakukan pekerjaan itu untuk Anda.
Ini adalah pembaruan untuk swift 3, metode ini harus ada di delegasi aplikasi Anda, dan Anda menyebutnya dari pengontrol tampilan apa pun, melalui instance bersama dari delegasi aplikasi
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)
}
Bagian yang hilang dari berbagai pertanyaan di atas, adalah
self.window?.makeKeyAndVisible()
Semoga ini bisa membantu seseorang.
di AppDelegate.h:
#define ApplicationDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)]
di Controller Anda:
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
ApplicationDelegate.window.rootViewController = newViewController;
}
completion:nil];
Saya mengusulkan cara saya yang berfungsi dengan baik dalam proyek saya, dan itu menawarkan saya animasi yang baik. Saya telah menguji proposal lain yang ditemukan di pos ini, tetapi beberapa di antaranya tidak berfungsi seperti yang diharapkan.
- (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];
}
Animasi manis yang bagus (diuji dengan Swift 4.x):
extension AppDelegate {
public func present(viewController: UIViewController) {
guard let window = window else { return }
UIView.transition(with: window, duration: 0.5, options: .transitionFlipFromLeft, animations: {
window.rootViewController = viewController
}, completion: nil)
}
}
Telepon dengan
guard let delegate = UIApplication.shared.delegate as? AppDelegate else { return }
delegate.present(viewController: UIViewController())