Objective-c – How to rotate an UIWebView embedded video

iphoneobjective crotationuiwebviewvideo

So I have this problem with an application I am building that I can't figure out.
My application has the following structure:

UITabBarController -> UIViewController -> UIViewController

The last view controller contains an UIWebView which loads an entire page. In that page there is a movie (mp4) that users can play once they hit the big round play button.

The application is made such that it runs in portrait mode, and there is no way I can do it run otherwise because of it's initial design.

What I want to achieve is let users rotate their phones once the movie starts playing and rotate the movie accordingly. I've managed to 'detect' when the movie is played by listening to different NSNotifications that NSNotificationsCenter sends.

I used this for detecting the start:

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(movieIsPlaying:)
name:@"UIMoviePlayerControllerDidEnterFullscreenNotification"
object:nil];

and this for detecting the end:

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(movieStopedPlaying:)
name:@"UIMoviePlayerControllerDidExitFullscreenNotification"
object:nil];

With the 2 selectors now I set one global variable to YES or NO which I can use later in

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation

If I always return YES from the above method my application interface rotates on every screen except when the movie is up and running. The weirdest thing is this:

  • I open the application in portrait.
  • Go to the desired page (see my structure above)
  • Rotate the phone to landscape (the interface rotates – this is just for debugging)
  • I start the movie (it launches in landscape! Hooray!)
  • I rotate the phone back to portrait (the movie rotates! Hooray again!)
  • I rotate the phone back to landscape (no more rotation occurs…)

Also if I start the movie in portrait mode it will never rotate.

Update

In the end I've come up with this solution for the 2 methods mentioned above:

- (void)movieIsPlaying:(NSNotification *)notification
{
    if (![Globals canRotateInterface]) {
        [Globals setCanRotateInterface:YES];
        
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
                
        [[[[notification object] view] window] setBounds:CGRectMake(0, 0, 480, 320)];
        [[[[notification object] view] window] setCenter:CGPointMake(160, 240)];
        [[[[notification object] view] window] setTransform:CGAffineTransformMakeRotation(M_PI / 2)];
    }
}

- (void)movieStopedPlaying:(NSNotification *)notification
{   
    if ([Globals canRotateInterface]) {
        [Globals setCanRotateInterface:NO];
        
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
        
        [[[[notification object] view] window] setBounds:CGRectMake(0, 0, 320, 480)];
        [[[[notification object] view] window] setTransform:CGAffineTransformIdentity];
                    
        // Little hack to force an orientation rotation so that all elements get their original size and place (eg. Navigation bar)
        UINavigationController *dummyNavigationViewController = [[UINavigationController alloc] init];
        [self presentModalViewController:dummyNavigationViewController animated:NO];
        [self dismissModalViewControllerAnimated:NO];
        [dummyNavigationViewController release];
    }
}

Best Answer

What I did in the end was use the 2 mentioned notifications to detect when the user plays or stops the movie and have code that rotates the window to 90 degrees. This way the user only sees the movie in landscape mode but it's better than just seeing it in portrait.

Related Topic