iOS - UI is not transforming with device rotation change - ios

I am working on orientation and Movie Player. The functionality is as follows:
If I turn on full screen mode of MPMoviePlayer then it should open in landscape mode only.
If I rotate my device to landscape, then it will automatically starts full screen mode of MPMoviePlayer
And again it should come back to portrait mode when I turn off
fullscreen mode of MPMoviePlayer or rotate device to portrait mode.
Now Problem is that, it goes to full screen mode on device rotation to landscape mode
but at the time of come back, The UI is not transforming to portrait mode properly.
This Problem is only with iOS 8.1, 8.2. It is working fine in iOS 7.* and 8.3, 8.4.
Please look at attached screens:
Before Full screen:
After full screen:
Come back to portrait mode:
I have used this code to handle orientation:
allowRotation is Boolean property declared in AppDelegate.h file
//Adding observer for movie player orientation event In App Delegate
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerWillEnterFullscreenNotification:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerWillExitFullscreenNotification:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
// Observer methods
- (void) moviePlayerWillEnterFullscreenNotification:(NSNotification*)notification {
allowRotation = YES;
}
- (void) moviePlayerWillExitFullscreenNotification:(NSNotification*)notification {
allowRotation = NO;
}
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
if (([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]] && ![[self.window.rootViewController presentedViewController] isBeingDismissed]) || allowRotation)
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
else{
allowRotation= NO;
return UIInterfaceOrientationMaskPortrait;
}
return UIInterfaceOrientationMaskPortrait;
}
Please help me to resolve this problem.

Do
In your UIViewController, implement
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
// Do the dynamic logic here
}
Don't
Do not ignore the window parameter passed in:
- (UIInterfaceOrientationMask)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window
Your current code is actually not responding to the question: ForWindow.
The general practice is to return
all the possible orientations for a given window (you typically only have a single window per application) in supportedInterfaceOrientationsForWindow
a subset of that list, which can be dynamic, in the view controller supportedInterfaceOrientations.
Example
// App delegate
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
// View controller
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}

Related

Programmatically rotate iOS app upside down using objective-c

I want to rotate my app upside down portrait using the following code in the ViewController:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{ //return NO;
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationMaskPortraitUpsideDown);
}
- (UIInterfaceOrientationMask) supportedInterfaceOrientations
{
return [super supportedInterfaceOrientations] | UIInterfaceOrientationMaskPortraitUpsideDown | UIInterfaceOrientationMaskPortrait;
}
In the AppDelegate:
- (UIInterfaceOrientationMask) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortraitUpsideDown | UIInterfaceOrientationMaskPortrait;
}
When the user presses a button
NSNumber * value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
The app does somehow not rotate and I have no idea why.
Somebody can give a hint?
Thank you
I added the orientations in the info.plist and set the checkboxes in the general settings in deployment info section.
Do I understand you correctly, that you want to programatically want to rotate the user interface, independend from the physical orientation of the device?
This is not how it works: The delegate methods (shouldAutorotate... etc.) are called by iOS when a (physical) rotation of the device is detected, e.g. the user turns it upside down. In the delegate methods you then get the chance to adopt the views to the new orientation, if you need to do so.
In the simulator, you can simulate device rotation by Alt+Left / Alt+Right keys.
You cannot rotate the orientation programatically it depends on sensors of the device. However you can rotate the layer of the view.
self.view.layer.transform = CGAffineTransformMakeRotation(M_PI_2);

Properly force or allow Landscape mode for Youtube embedded video in iOS 8 without NSNotificationCenter

I am having issues of capturing when the youtube player will enter in fullscreen or exit fullscreen in iOS 8 because these notifications were removed UIMoviePlayerControllerDidEnterFullscreenNotification and UIMoviePlayerControllerWillExitFullscreenNotification for this version OS version.
Because my app project is set to be only in portrait mode the video won't rotate to landscape mode when is playing which is really not too user friendly when watching a video on your device.
Usually the user would like to watch the video either in portrait mode or landscape mode when the video enters in fullscreen.
These is the way I was doing it for iOS 7 which was working perfect but not in iOS 8.
First, I will set this function in my AppDelegate.m with boolean property in my AppDelegate.h which I called videoIsInFullscreen and function,
// this in the AppDelegate.h
#property (nonatomic) BOOL videoIsInFullscreen;
// This in my AppDelegate.m to allow landscape mode when the boolean property is set to yes/true.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
if(self.videoIsInFullscreen == YES)
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else
{
return UIInterfaceOrientationMaskPortrait;
}
}
Then within my ViewController.m First, I would #import "AppDelegate.h" after doing this, I will add some notifications in my viewDidLoad method..
-(void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerStarted) name:#"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerEnded) name:#"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];
}
Of course don't forget to remove them..
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];
}
Then, I had my functions that will get call when these notifications get fires... Here is where I allow the landscape mode and then set it back to portrait. These is the case with my app because it's only set to portrait support but I don't want this for the youtube videos.
// first we set our property in the our AppDelegate to YES to allow landscape mode
- (void)playerStarted
{
((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = YES;
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
}
// Then I will set the property to NO and force the orientation to rotate to portrait.
- (void)playerEnded
{
((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = NO;
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
}
But, these is not the case for iOS 8.. These notifications no longer work for iOS 8 so, I found something similar using these notifications but I am not too happy because they are not 100% accurate for the video player. UIWindowDidBecomeVisibleNotification and UIWindowDidBecomeHiddenNotification So, how can I do this correctly or at least that works properly for my youtube embedded video and allow landscape mode in iOS 8...?
So, after some research and looking more in-depth to this problem.. I came to a solution using the UIWebView delegates, plus I had to solve another issue in terms of my function - (void)playerEnded which it wasn't working properly in the new iPhone 6 devices..
This is how I did it.. First, in my webViewDidFinishLoad method I have added to my webview a javascript evaluation to check when this video player goes into fullscreen mode..
- (void)webViewDidFinishLoad:(UIWebView*)webView
{
// adding listener to webView
[_webView stringByEvaluatingJavaScriptFromString:#" for (var i = 0, videos = document.getElementsByTagName('video'); i < videos.length; i++) {"
#" videos[i].addEventListener('webkitbeginfullscreen', function(){ "
#" window.location = 'videohandler://begin-fullscreen';"
#" }, false);"
#""
#" videos[i].addEventListener('webkitendfullscreen', function(){ "
#" window.location = 'videohandler://end-fullscreen';"
#" }, false);"
#" }"
];
}
Then, in my - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType method, I check when my request url matches the state of the youtube player, like this..
This will fire our function to allow landscape mode or force back to portrait mode.. or maybe any other type of work you might want to do..
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// allows youtube player in landscape mode
if ([request.URL.absoluteString isEqualToString:#"ytplayer://onStateChange?data=3"])
{
[self playerStarted];
return NO;
}
if ([request.URL.absoluteString isEqualToString:#"ytplayer://onStateChange?data=2"])
{
[self playerEnded];
return NO;
}
}
And finally, I needed to adjust my playerEnded function to force back portrait mode for iPhone 6 devices..
- (void)playerEnded
{
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:#"orientation"];
((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = NO;
[self supportedInterfaceOrientations];
[self shouldAutorotate:UIInterfaceOrientationPortrait];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
}
Almost, missed I also added these two other functions..
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
So, finally I am able to catch the state of the actual player and fire my functions to do some work or whatever I want at the right moment, in my case changing the orientation..
I hope this helps someone else..
I am working on swift, I my player runs movie in both portrait and landscape direction. First I checked three modes : portrait, landscapeleft, landscaperight.
Second I wrote this function in all viewController:
isFullScreen = false
override func shouldAutorotate() -> Bool {
if isFullScreen == true {
return true
}else{
return false
}
}
Third I change the value of isFullScreen in this function:
func playerView(playerView: YTPlayerView!, didChangeToState state: YTPlayerState) {
switch (state) {
case YTPlayerState.Playing:
println("started to play")
isFullScreen == true
shouldAutorotate()
case YTPlayerState.Paused:
println("paused")
default:
println("non of sttate")
break
}
}
And video runs on both portrait and landscape mode! The interesting thing is that I dont set isFullScreen to false again when I pause video or move from fullscreen. However it doesnt rotate! Can somebody explain this?

Autorotating ViewController after dismissing MPMoviePlayerViewController

Before you vote this question down, note, that I've already tried to implement all the solutions available on stackoverflow. Here is the issue:
My application runs only in portrait mode. The only thing which needs to be in landscape is video player. When a user taps on my TableViewCell this block of code is called:
MPMoviePlayerViewController *moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:videoUrl];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
After that, I need to give the user the ability to watch video both in portrait and landscape mode. After he is done, everything should get back into portrait mode. I've tried to call this block of code in my AppDelegate.m:
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if ([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]]) {
orientations = UIInterfaceOrientationMaskAllButUpsideDown;
}
return orientations;
}
With it everything is fine except one thing - when the video is over or when the user taps "Done" button while in landscape mode, my view controller appears in landscape mode too.
Besides it, I've tried a lot of other methods - but nothing seems to work.
I'll be glad for any help!
Thanks #Shubham - Systematix for the answer.
All that I had to do was to remove every code related to autorotating except this method in AppDelegate:
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if ([[window.rootViewController presentedViewController] isKindOfClass: [MPMoviePlayerViewController class]])
{
//NSLog(#"in if part");
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else
{
//NSLog(#"in else part");
return UIInterfaceOrientationMaskPortrait;
}
}
When I did it everything worked like a magic!

iOS 7 Interface Orientation

I have an app that is always showed in portrait mode.
But in somewhere i have a media gallery that must support landscape.
The supported orientation by default in the project is portrait. Because of that the gallery is only showed in portrait mode.
If i change the project setting to show in portrait and landscape the gallery works fine but i can't control the other viewControllers to show only in portrait.
I tried several methods like shouldAutoRotate but no one worked.
Any ideia how to solve?
Regards
EDIT:
Solved :)
First i configured the project to support all orientation.
Then i added this method to the AppDelegate.m:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape;
}
After this what i did was to block orientation in each view controller, less the one i want to have orientation in landscape and portrait.
Code to block orientation (iOS 7):
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskPortrait);
}
Thanks to everyone that answered me :)
In my app for iPhone its only support the portrait view only, but as per requirement need to support landscape view only for on view, at that time I use following way and its help me :
In your app delegate .h
#interface PlayWithWSWithLibAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
BOOL flagOrientationAll;
}
#property (assign) BOOL flagOrientationAll;
Add following method in your app delegate .m file
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
//NSLog(#"PlayWithWSWithLibAppDelegate -- supportedInterfaceOrientationsForWindow");
if([UICommonUtils isiPad]){
return UIInterfaceOrientationMaskAll;
}else if(flagOrientationAll == YES){
return UIInterfaceOrientationMaskAll;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
Implement following way in your view which you want to rotate in both portrait and landscape both for iPhone device
-(void)viewWillAppear:(BOOL)animated
{
self.tabBarController.delegate = self;
PlayWithWSWithLibAppDelegate *delegate = (PlayWithWSWithLibAppDelegate *) [[UIApplication sharedApplication] delegate];
delegate.flagOrientationAll = YES;
}
}
-(void)viewWillDisappear:(BOOL)animated
{
//NSLog(#"viewWillDisappear -- Start");
PlayWithWSWithLibAppDelegate *delegate = (PlayWithWSWithLibAppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.flagOrientationAll = NO;
}
see this post also: How to set one of the screens in landscape mode in iphone?
You have to make another class in the same view Controller where you are presenting your media.
In that you can specify your orientation where it will support only landscape orientation only when you will present your media.
I am giving you an example of my app which supports only in landscape mode but as I took Image picker and it supports only in portrait mode so I changed the orientation for only that view.
#pragma mark - Image PICKER
#interface NonRotatingUIImagePickerController : UIImagePickerController
#end
#implementation NonRotatingUIImagePickerController
- (BOOL)shouldAutorotate
{
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait ;
}
#end
Then when I used ImagePicker I used object of the class that i made.
So I define like below.
UIImagePickerController* picker = [[NonRotatingUIImagePickerController alloc] init];
So For Image Picker It showed only in portrait mode.
You just need to change Landscape instead of portrait if you want only Landscape Orientation for your particular view where you want to change it.
Hope this helps you.

How to autorotate UIView based on device orientation iOS 6?

I have started my project with iOS 5.0, Now updated to iOS 6, I am facing problem in doing orientation, To test I have created a sample application, and added the following code in delegate...
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskAll;
}
And in my view controller I have implemented the following methods...
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
-(BOOL)shouldAutorotate
{
return YES;
}
All the above I have done after googled about iOS 6.0,when I load application, based on the option given in supportedInterfaceOrientations view is loading that is fine, now when I changes my device orientations... view is not changing accordingly at run time, how do I change my view based on the device orientation?
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[notificationCenter addObserver:self
selector:#selector(deviceOrientationDidChange)
name:UIDeviceOrientationDidChangeNotification object:nil];
Do I need to add observer like above and changes it programmatically? or Will the view change automatically by detecting device orientation?
try this
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
- (BOOL) shouldAutorotate {
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscape;
}
The previous code should work on iOS6
Anyways, I use this code on one of my projects. I have a boolean _firstTime, and I set it to YES before showing the viewController, then I change it to NO after the viewController appears
- (NSUInteger)supportedInterfaceOrientations {
if (_firstTime) {
return UIInterfaceOrientationMaskLandscape;
} else {
return UIInterfaceOrientationMaskAll;
}
}
- (BOOL) shouldAutorotate {
return YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (_firstTime) {
return return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft)||(interfaceOrientation == UIInterfaceOrientationLandscapeRight);
} else {
return YES;
}
}
Change in these method:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
Note : No need to add observer for device notification.Given below method will specify orientation status
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
EDIT : Provide all your views will automasking according to requirement
EDIT : If using UINavigation Controller then its child View Controller's supportedInterfaceOrientations and shouldAutorotate method will not be called.
Refer this link.
Problem is with my iPad. it has a button to restrict auto rotation change... I was not aware initially, as I was worked fully with iPod.. Thanks all for your helps.

Resources