I have a UIWebView included in a UIViewController which is a descendant of UINavigationController. It looks like this:
I faced this problem yesterday, where @entropid answer worked for iOS 9 and below, but for iOS 10 it didn't (since iOS 10 did actually hide the status bar, where on iOS 9 and below it was just the UINavigationBar
that changed its frame without hiding the status bar and, thus, it overlapped that bar).
Also, subscribing to MPMoviePlayerControllerDidExitFullScreen
notification didn't work either, sometimes it simply wasn't called (in my particular case, it was because it was a video from a UIWebView
, which used a different class of player which looks similar to MPMoviePlayerController
).
So I solved it using a solution like the one @StanislavPankevich suggested, but I subscribed to notifications when a UIWindow
has become hidden (which can be in several cases, like when a video has finished, but also when a UIActivityViewController
dismisses and other cases) instead of viewWillLayoutSubviews
. For my particular case (a subclass of UINavigationController
), methods like viewDidAppear
, viewWillAppear
, etc. simply weren't being called.
viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(videoDidExitFullscreen:)
name:UIWindowDidBecomeHiddenNotification
object:nil];
// Some other logic...
}
dealloc
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
And finally, videoDidExitFullscreen
- (void)videoDidExitFullscreen:(NSNotification *)notification {
// You would want to check here if the window dismissed was actually a video one or not.
[[UIApplication sharedApplication] setStatusBarHidden:NO
withAnimation:UIStatusBarAnimationFade];
}
I used UIStatusBarAnimationFade
because it looks a lot smoother than UIStatusBarAnimationNone
, at least from a user perspective.
My answer on this question works great. Here It will play the video inside your WebView normally but if you tilt your phone it will play in Landscape!
Also important to note is if you include youtube.com as the Base URL it will load much quicker.
Make a UIWebView in your storyboard and connect the @property to it, then reference below.
CGFloat width = self.webView.frame.size.height;
CGFloat height = self.webView.frame.size.width;
NSString *youTubeVideoCode = @"dQw4w9WgXcQ";
NSString *embedHTML = @"<iframe width=\"%f\" height=\"%f\" src=\"http://www.youtube.com/embed/%@\" frameborder=\"0\" style=\"margin:-8px;padding:0;\" allowfullscreen></iframe>";
NSString *html = [NSString stringWithFormat:embedHTML, width, height, youTubeVideoCode];
self.webView.scrollView.bounces = NO;
[self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.youtube.com"]];
I was having the same issue and using @entropid solution I was able to fix the navigation bar problem. But my view remains below the nav bar which I fix using "sizeToFit".
[[NSNotificationCenter defaultCenter] addObserverForName:@"UIWindowDidRotateNotification" object:nil queue:nil usingBlock:^(NSNotification *note) {
if ([note.userInfo[@"UIWindowOldOrientationUserInfoKey"] intValue] >= 3) {
[self.navigationController.navigationBar sizeToFit];
self.navigationController.navigationBar.frame = (CGRect){0, 0, self.view.frame.size.width, 64};
}
}];
I haven't tested it properly but its working for me right now
I temporarily solved (through a hack) with the following code in the viewDidLoad
of my controller. I have to specify that the code is specifically made for my case: since I explicitly disallow landscape orientation of my UINavigationController (see code above), the usual notification “UIDeviceOrientationDidChange” is not called when the playback finished and the window goes back to portrait. However, I hope there is a better option and this is a bug of the SDK, since it does not appear on iOS 7 and given the amount of auto-layout errors I get related to the video player (on which I have no control).
- (void)viewDidLoad
{
[super viewDidLoad];
// […]
/*
Hack to fix navigation bar position/height on iOS 8 after closing fullscreen video
Observe for “UIWindowDidRotateNotification” since “UIDeviceOrientationDidChangeNotification” is not called in the present conditions
Check if the notification key (“UIWindowOldOrientationUserInfoKey”) in userInfo is either 3 or 4, which means the old orientation was landscape
If so, correct the frame of the navigation bar to the proper size.
*/
[[NSNotificationCenter defaultCenter] addObserverForName:@"UIWindowDidRotateNotification" object:nil queue:nil usingBlock:^(NSNotification *note) {
if ([note.userInfo[@"UIWindowOldOrientationUserInfoKey"] intValue] >= 3) {
self.navigationController.navigationBar.frame = (CGRect){0, 0, self.view.frame.size.width, 64};
}
}];
}
And then…
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:@"UIWindowDidRotateNotification"];
}
It's very simple, as it says @Stanislav Pankevich, but in
swift 3 version
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews();
UIApplication.shared.isStatusBarHidden = false
}
Swift version:
//AppDelegate:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
var presentedVC = application.keyWindow?.rootViewController
while let pVC = presentedVC?.presentedViewController
{
presentedVC = pVC
}
if let pVC = presentedVC
{
if contains(["MPInlineVideoFullscreenViewController", "MPMoviePlayerViewController", "AVFullScreenViewController"], pVC.nameOfClass)
{
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
}
}
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
//Extension:
public extension NSObject{
public class var nameOfClass: String{
return NSStringFromClass(self).componentsSeparatedByString(".").last!
}
public var nameOfClass: String{
return NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last!
}
}
//View controller:
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.Portrait
}
override func shouldAutorotate() -> Bool {
return false
}
override func viewWillLayoutSubviews() {
UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: UIStatusBarAnimation.None)
}