简体   繁体   中英

Change interface orientation when back button is pressed

My app accepts only portrait orientation, except for MPMoviePlayerController , which I want to allow user to change orientation.

So, I subclassed UINavigationController and added the following code:

-(BOOL)shouldAutorotate
{
    if ([[[self.viewControllers lastObject] presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]])
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

It works great, allowing only my MPMoviePlayerViewController to change orientation. The problem is that when user is in landscape orientation and presses the done button or playback ends, it pops the moviePlayer and goes back to the presentingViewController, but on landscape mode, causing a crash, since that view is not made for landscape orientation.

I tried a few things to change back to Portrait but had no luck. I'm using storyboards, if that makes any difference. I would like to change the orientation back to portrait on viewWillAppear , or maybe getting the done button press and change the orientation there.

UPDATE:

Here is the updated code in my UINavigationController subclass:

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    if ([[[self.viewControllers lastObject] presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]])
    {
        return UIInterfaceOrientationMaskAll;
    }
    else
    {
        return UIInterfaceOrientationMaskPortrait;
    }
}

Now, if I do things in the following order from the view with the Play button .

  1. Rotate the device. (it calls the method but screen doesn't rotate since it is not MPMoviePlayerController class)
  2. Press the play button . (It presents the player already on landscape mode).
  3. Press the back button. (It pops the player and correctly shows the view on portrait mode)

Now, if I change the order to:

  1. Press the play button. (holding the device on the regular portrait position).
  2. Rotate the device. (it rotates the movie player correctly showing the video).
  3. Press the back button. (it pops the player, but this time, the view is in landscape mode, which is not the expected behavior)

Found a solution here on this answer .

On button click, I added a notification and then on done button click I used the below code to change orientation. I kept the UINavigationController subclass as in my question to allow the change of orientation when movie starts playing.

- (IBAction)playButton:(id)sender {        
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(moviePlaybackDidFinish)
                                                 name:MPMoviePlayerPlaybackDidFinishNotification
                                               object:self.player.moviePlayer];

    NSURL *url = [NSURL URLWithString:@"https://dl.dropboxusercontent.com/s/crzu6yrwt35tgej/flexao.mp4"];        
    self.player = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
    self.player.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
    [self presentMoviePlayerViewControllerAnimated:self.player]; // presentMoviePlayerViewControllerAnimated:self.player];
}

-(void)moviePlaybackDidFinish
{
    [[UIDevice currentDevice] setValue:
     [NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
                                forKey:@"orientation"];
}

I have a working configuration for your problem, as far as I understand from your question.

You need a subclass of UINavigationController as you already have, but with the following code:

The .h file:

@interface EECNavigationController : UINavigationController

@property (assign, nonatomic) BOOL landscapeDisallowed;

@end

The .m file:

#import "EECNavigationController.h"

@implementation EECNavigationController

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if( !_landscapeDisallowed ) {
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskPortrait;
}

@end

Now, in the view controllers that will be under this navigation controller that you want to be just portrait you just need to set the "landscapeDisallowed" to YES in the viewDidLoad method, like:

- (void)viewDidLoad {
    [super viewDidLoad];

    ((EECNavigationController *)self.navigationController).landscapeDisallowed = YES;
}

And override the following methods like this:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return toInterfaceOrientation == UIInterfaceOrientationPortrait;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

The views that can be presented in landscape mode just need to:

- (void)viewDidLoad {
    [super viewDidLoad];

    ((EECNavigationController *)self.navigationController).landscapeDisallowed = NO;
}

It works for me, hope it works for you.

-(void)viewWillAppear:(BOOL)animated
{


       [self updateLayoutForNewOrientation:self.interfaceOrientation];
}
- (void)updateLayoutForNewOrientation:(UIInterfaceOrientation)orientation
{
    if (self.interfaceOrientation == UIInterfaceOrientationPortrait || self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
    {
        // Portrait view

        if(iPhone5)

        {
        }else{

        }

        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
        {

        }


    }

    else
    {
        // Landscape view

        if(iPhone5)

        {


        }else{
            float SystemVersion=[[[UIDevice currentDevice] systemVersion] floatValue];
            if(SystemVersion>=7.0f)
            {


            }else{

            }
        }

        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
        {
            if(iPhone5)
            {

            }
            else
            {

            }
        }


    }
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
    [self updateLayoutForNewOrientation:self.interfaceOrientation];
}

Hope this will help

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM