Good slide transition between full-screen and full-screen UIViewController

I have a view controller that is not full-screen (has a status bar) and wants to present a modal view controller that is full-screen.

If I hide the status bar at the beginning of the animation (the parent view of WillDisappear or modal viewWillAppear), for a moment the parent will be visible without a status bar, looking like an error.

If I do this at the end of the animation (parent viewDidDisappear or modal viewDidAppear), then the status bar will be visible momentarily on top of the modal view, i.e. it will not appear as a modal representation of "covered it."

Is there any way to make it beautiful?

change

One possibility would be to create a UIWindow with windowLevel = alert for at least the duration of the animation. The iAd ad sample seems to well illuminate the status bar without another window, so it should be somehow.

+6
source share
5 answers

Another interesting little project. That was the best I could think of. This is not so bad if you do not mind using your own container controller to control the presentation / dismissal of view controllers. I am trying to do something in common, but it can be included in the w / ContainerViewController application, if necessary.

Please note that I performed only the equivalent of UIModalTransitionStyleCoverVertical . You can also customize the animation as you like.

Corresponding animation code:

 - (void)presentViewController:(UIViewController *)viewControllerToPresent { // do nothing if no controller if (!viewControllerToPresent) return; [__viewControllers addObject:viewControllerToPresent]; CGRect toFrame = viewControllerToPresent.view.frame; toFrame.origin = CGPointMake(0, CGRectGetMaxY(self.view.bounds)); viewControllerToPresent.view.frame = toFrame; [UIView transitionWithView:self.view duration:0.2 options:UIViewAnimationOptionTransitionNone animations:^{ [[UIApplication sharedApplication] setStatusBarHidden:viewControllerToPresent.wantsFullScreenLayout withAnimation:UIStatusBarAnimationSlide]; [self.view addSubview:viewControllerToPresent.view]; viewControllerToPresent.view.frame = [UIScreen mainScreen].applicationFrame; } completion:nil]; } - (void)dismissViewController { // nothing to dismiss if showing first controller if (__viewControllers.count <= 1) return; UIViewController *currentViewController = [__viewControllers lastObject]; UIViewController *previousViewController = [__viewControllers objectAtIndex:__viewControllers.count - 2]; [UIView transitionWithView:self.view duration:0.2 options:UIViewAnimationOptionTransitionNone animations:^{ [[UIApplication sharedApplication] setStatusBarHidden:previousViewController.wantsFullScreenLayout withAnimation:UIStatusBarAnimationSlide]; CGRect toFrame = currentViewController.view.frame; toFrame.origin = CGPointMake(0, CGRectGetMaxY(self.view.bounds)); currentViewController.view.frame = toFrame; } completion:^(BOOL finished) { [currentViewController.view removeFromSuperview]; [__viewControllers removeLastObject]; }]; } 
+4
source

I am doing this in my application using this code:

 [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque]; [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation: UIStatusBarAnimationSlide ]; DocumentListViewController * dl = [[DocumentListViewController alloc] initWithNibName:@"DocumentListView" bundle:nil] ; UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:dl]; [dl release]; // Go to the list of documents... [[self.view superview] addSubview:nav.view]; nav.view.alpha = 0.0 ; [self hideActivityAlert]; [UIView animateWithDuration:1.0 animations:^{ nav.view.alpha = 1.0; } completion:^(BOOL A){ [self.view removeFromSuperview]; [self release];} ]; 

The status bar is displayed during the animation.

You must be sure that the first view, when the status bar is hidden, fills the gap. Use the autoresizingMask property with the correct value.

0
source

Here is a solution that seems to work. You can get the viewcontroller that you want to present modally from my TSFullScreenModalViewController, or you can just implement the code directly in the view controller itself.

 @interface TSFullScreenModalViewController : UIViewController { UIWindow* _window; } - (void) presentFullScreenModal; @end @implementation TSFullScreenModalViewController - (void) viewDidDisappear:(BOOL)animated { [super viewDidDisappear: YES]; [_window resignKeyWindow]; [_window release]; _window = nil; } - (void) presentFullScreenModal { UIViewController* rvc = [[UIViewController new] autorelease]; rvc.view.backgroundColor = [UIColor clearColor]; _window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds] ; _window.windowLevel = UIWindowLevelStatusBar+1; _window.backgroundColor = [UIColor clearColor]; _window.rootViewController = rvc; [_window makeKeyAndVisible]; [UIApplication sharedApplication].statusBarHidden = YES; [rvc presentModalViewController: self animated: YES]; [UIApplication sharedApplication].statusBarHidden = NO; } @end 

Print your modal view controller, for example:

 @interface MyModalViewController : TSFullScreenModalViewController { } - (IBAction) onDismiss:(id)sender; @end 

Use it from another view controller, for example:

 - (IBAction) onShowModal:(id)sender { MyModalViewController* mmvc = [[MyModalViewController new] autorelease]; [mmvc presentFullScreenModal]; } 

Finally, release the view controller, as usual:

 - (IBAction) onDismiss:(id)sender { [self dismissModalViewControllerAnimated: YES]; } 
0
source

Maybe a little hack, but you thought:

  • Take a programmatic screenshot of the first view with a status bar (see this SO question )
  • Create a new view that displays the image you just made in full screen (using UIImage initWithFrame )
  • Hide status bar
  • Introduce a modal view controller

Then, to reject the view of modality, simply undo the steps.

EDIT

Does not work for this because you cannot take screenshots of the status bar.

0
source

It can be as simple as delaying the presentation of your modalViewController using the performSelector: withDelay function:

Tell the status bar to animate, and then run the modal controller with the correct delay so that it matches the animation of the status bar.

0
source

Source: https://habr.com/ru/post/903548/


All Articles