How to dismiss a modal VC with fade out animation?
Asked Answered
P

3

17

I am using the following code in my presenting VC to fade in the child modal VC, and this works fine:

self.infoViewController.view.alpha = 0.0;
[self.navigationController presentModalViewController:self.infoViewController animated:NO];
[UIView animateWithDuration:0.5
             animations:^{self.infoViewController.view.alpha = 1.0;}];

However I can't get it to fade out, I have tried a few things, this is the latest I tried that doesn't work:

- (IBAction)dismissAction:(id)sender
{
if ([[self parentViewController] respondsToSelector:@selector(dismissModalViewControllerAnimated:)])
{
    [[self parentViewController] dismissModalViewControllerAnimated:YES];
    self.parentViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    self.parentViewController.view.alpha = 0.0;
    [UIView animateWithDuration:0.5
                     animations:^{self.parentViewController.view.alpha  = 1.0;}];
} else 
{
    [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
    self.presentedViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    self.presentedViewController.view.alpha = 0.0;
    [UIView animateWithDuration:0.5
                     animations:^{
                         self.presentedViewController.view.alpha  = 1.0;}];
}

}

The modal view controller is faded out but immediately, not over a time period like it is when its displayed.

Pyrology answered 21/1, 2012 at 21:46 Comment(2)
If you do want this code to run on devices earlier than iOS 5 you'll need to protect the call to presentedViewController as well as dismissModalViewControllerAnimated.Timberwork
If you're seeing a dismiss animation, it sure sounds like this code is getting executed and it's getting dismissed through another path.Timberwork
D
51

This (original part) is not to take away from H2CO3's correct answer. UIModalTransitionStyleCrossDissolve does pretty-much exactly the effect you're looking for. You are just not setting the modalTransitionStyle until it's to late. Replace all of your code with these functions in there respective positions:

-(void)show{
    self.infoViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self presentModalViewController:self.infoViewController animated:YES];
}
- (IBAction)dismissAction:(id)sender{
    [self dismissModalViewControllerAnimated:YES];
}

Edit in response to timing being an issue: Let's talk about the offending code. We'll concentrate on just the if true part, since it's essentially identical to the else.

[[self parentViewController] dismissModalViewControllerAnimated:YES];
self.parentViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.parentViewController.view.alpha = 0.0;
[UIView animateWithDuration:0.5
                 animations:^{self.parentViewController.view.alpha  = 1.0;}];

If you're looking for a reciprocal animation this isn't it. In your original animation you set the next view's alpha to 0, then presented the next view controller, then set it's view's alpha to 1. So logically you need to dismiss the view controller after the animation; This is really easy using blocks. The code would look something like this:

[UIView animateWithDuration:0.5 animations:^{
    self.view.alpha = 0;
} completion:^(BOOL b){
    [self.presentingViewController dismissModalViewControllerAnimated:NO];
    self.view.alpha = 1;
}];

This line of code animates the view's alpha to 0, then (upon completion) dismisses the presented view controller, and sets the view's alpha back to 1. This is a reciprocal animation.

Delao answered 22/1, 2012 at 1:38 Comment(3)
Thanks, but both yourself and H2CO3 are ignoring that fact that there is a withDuration part in my code. WIth the reduced code there is no way to set how long the fade in/out should take. And my posting says ".. but not over a time period". Apologies my title maybe should have said how to achieve fade out AND control its duration, but I thought it was obvious from the code posted and description, sorry if it was not.Pyrology
Edited in response to commentDelao
It seems that in iOS8 you need to add self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve also on presentingViewController, so dismiss is also CrossDissolveConfusion
P
11

In the docs of UIViewController, we can find:

@property(nonatomic, assign) UIModalTransitionStyle modalTransitionStyle

Set this property to UIModalTransitionStyleCrossDissolve and it will dissolve properly :)

Hope that helps.

Pediatrician answered 21/1, 2012 at 22:5 Comment(4)
Thank you, it dissolves, but it does so immediately, while I have a .5 second animation on its appearance. How can I make it dissolve slowly?Pyrology
[self.parentViewController dismissModalViewControllerAnimated:YES];Pediatrician
Setting Animated: to YES makes it scroll off, setting Animated: to NO makes it dissolve away, but still immediately. I've posted my latest code in an edit above.Pyrology
Marking this as accepted as it answers the title of my query, although I'm still seeking the answer regarding how to achieve fade with a duration for it set.Pyrology
R
0

I guess, this might be useful for those heroic guys, who still tries to use MPMoviePlayerViewController in full screen mode and with orientation, which differs from the app major one.

I've spent literally a half of working day playing with presenting MPMoviePlayerViewController modally or not modally. But there is no luck with that at all, in sense of transition animation changing. (The modal mode needed for setting orientation which differs from the app major orientation).

I tried presentViewController or presentModalViewController, but the result is the same. No matter what type is the modalTransitionStyle property set, if I do [... dismissViewControllerAnimated:true ...] then default transition style (UIModalTransitionStyleCoverVertical) used anyway. I tested that in iOS 5.1 device and in iOS 6 Simulator.

I haven't tried any other types of controllers... Considering that common controller has method dismissMoviePlayerViewControllerAnimated, I can assume, that this method is used anyway for dismissing a video controller, no matter how did it appear. (Entering transitions didn't work for me as well, except they did not process as CoverVertical (in case of modalTransitionStyle changing).

So, my solution was not use the transition animation at all. I am sure, Apple had some reasons for allowing only some definite animation for MovieViewController (I really hope so, and that was made not because of "laziness"), but if they wanted some nice experience user would get, they failed, as in my app that's even better when the video appears without any animation (which is worse than CrossDisolving for sure) but that's better than banal CoverVertical.

Looking on that from developer's point of view, it really sounds like they spend much more money for designers to paint nice icons for customers instead of more pleasant and effective work of developers. (

Rola answered 10/11, 2012 at 0:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.