Autorotating video played from HTML5 <video>

2019-02-10 04:56发布

问题:

My app, for some reasons, only supports portrait orientation.
However, in some cases I need to display videos from a UIWebView (with video tag) and it would be nice if the user can view it either in portrait or landscape.

The controller is configured like this:

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

Result: the video is played only in portrait mode (ok, quite expected).

I tried:
- setting this to support all orientations when the user starts a video
- when the video stops, back to "portrait only"

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    // autorotationEnabled is toggled when a video is played / stopped
    return autorotationEnabled ? YES : UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}

Result: landscape mode is available (great!) but if the user taps 'Done' while playing in landscape, the previous view will appear in landscape mode once the player is dismissed (not so great).

Does anybody have an idea on how to prevent the controller from being displayed in landscape mode when the player is dismissed?
(using the private method setInterfaceOrientation of UIDevice is not an option)

回答1:

I've have done something very similar. You have to modify the UIView stack to force the app to call shouldAutorotateToInterfaceOrientation when you pop the controller.

In your WebViewController set to allow the autorotate:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return YES;
}

In the parent controller disallow autorotate:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

Create and assign a UINavigationControllerDelegate.
In the delegate, temporarily modify the UIView stack when the controller pops or pushes:

- (void)navigationController:(UINavigationController *)navigationController 
  willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

// Force portrait by changing the view stack to force autorotation!
if ([UIDevice currentDevice].orientation != UIInterfaceOrientationPortrait) {
    if (![viewController isKindOfClass:[MovieWebViewController class]]) {
        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        UIView *view = [window.subviews objectAtIndex:0];
        [view removeFromSuperview];
        [window insertSubview:view atIndex:0];
    }
}

It's kind of a dirty hack, but it works.