on iPad ios 9+, with objective-c :
- lock the orientation outside of your app
- in code: how to detect when the device changes the orientation?
I have tried all possibilities:
1) try to catch UIDeviceOrientationDidChangeNotification event:
- (void)subscribeOrientationChangeEvent {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
}
- (void) orientationChanged:(NSNotification *)note {
NSLog("Device rotated");
}
2) override viewWillTransitionToSize method
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
NSLog("Device rotated");
}
3) use KVO to see if the value orientation of [UIDevice currentDevie]
4) use KVO to see if the value statusBarOrientation of [UIApplication sharedApplication]
5) set Require FullScreen for the setting StatusBarStyle
reference: link
apply this setting and combine with all above attempts, but all failed.
6) using Accelerometer (CMMotionManager)
Any advice? thanks a lot
If the device orientation is lock; your app will have to abide by it. You won't be able to detect orientation for obvious reasons. So the short answer is you can't.
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;
}
I am attempting to make the youtube video that is in my UIWebView go into landscape but my application is only set to portrait and i don't want anything else to be landscape. I have already tried many things for example supporting landscape and on all the other views returning no to landscape but its not working. My project is a tab based application. If i have to the whole view can rotate and not just the video but if just the youtube video could rotate once its gone into fullscreen(which happens automatically) it would be brilliant.
You could make your controller subscribe to the UIDeviceOrientationDidChangeNotification notification and from the method handling the notification rotate just the UIWebView containing the video.
This would be something like this:
[[NSNotificationCenter defaultCenter] addObserver:self
selector: #selector(handleOrientationChangeNotification:)
name: UIDeviceOrientationDidChangeNotification object:nil];
-(void)handleOrientationChangeNotification:(NSNotification *)notification
{
UIDeviceOrientation currentDeviceOrientation = [[UIDevice currentDevice] orientation];
if (currentDeviceOrientation == UIDeviceOrientationLandscapeRight) {
webView.transform = CGAffineTransformRotateMake(M_PI_2);
webView.bounds = (CGRect){480,320};
webView.center = (CGPoint){240,160};
} else if (...
...
}
I created an UIWebView inside an UIViewController. This web view contains a youtube video page like this one: http://www.youtube.com/watch?v=oL1RE8JXaIw
When I click on the video link, the iOS video player is launched. Everything is going well till here.
The problem is that when I rotate my application (in landscape mode) and I click on the done button, my View Controller is in landscape mode.
So I've added this callback in the view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return NO;
}
but nothing has changed.
Any idea?
That orientation code is invalid - make sure to always return YES for at least one orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return UIInterfaceOrientationPortrait;
}
I handled that problem using NSNotification like this in viewDidLoad method
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerDidExitFullScreen)
name:#"UIMoviePlayerControllerDidExitFullscreenNotification"
object:nil];
and this method will call when video ends and you can do necessary changes
- (void)moviePlayerDidExitFullScreen
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
}
Hope that Helps
In a given event handler (not the "shouldAutorotateToInterfaceOrientation" method) how do I detect the current iPad orientation? I have a text field I have to animate up (when keyboard appears) in the Landscape view, but not in the portrait view and want to know which orientation I'm in to see if the animation is necessary.
Orientation information isn't very consistent, and there are several approaches. If in a view controller, you can use the interfaceOrientation property. From other places you can call:
[[UIDevice currentDevice] orientation]
Alternatively, you can request to receive orientation change notifications:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
Some people also like to check the status bar orientation:
[UIApplication sharedApplication].statusBarOrientation
I think
[[UIDevice currentDevice] orientation];
is not really reliable. Sometimes it works, sometimes not... In my apps, I use
[[UIApplication sharedApplication]statusBarOrientation];
and it works great!
One of:
Check the interfaceOrientation property of the active view controller.
[UIApplication sharedApplication].statusBarOrientation.
[UIDevice currentDevice].orientation. (You may need to call -beginGeneratingDeviceOrientationNotifications.)
I found a trick to solve the FaceUp orientation issue!!!
Delay the orientation check till AFTER the app has started running, then set variables, view sizes, etc.!!!
//CODE
- (void)viewDidLoad {
[super viewDidLoad];
//DELAY
[NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(delayedCheck)
userInfo:nil
repeats:NO];
}
-(void)delayedCheck{
//DETERMINE ORIENTATION
if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait ){
FACING = #"PU";
}
if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown ){
FACING = #"PD";
}
if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft ){
FACING = #"LL";
}
if( [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight ){
FACING = #"LR";
}
//DETERMINE ORIENTATION
//START
[self setStuff];
//START
}
-(void)setStuff{
if( FACING == #"PU" ){
//logic for Portrait
}
else
if( FACING == #"PD" ){
//logic for PortraitUpsideDown
}
else{
if( FACING == #"LL"){
//logic for LandscapeLeft
}
else
if( FACING == #"LR" ){
//logic for LandscapeRight
}
}
//CODE
You can addSubviews, position elements, etc. in the 'setStuff' function ... anything that would initially depend on the orientation!!!
:D
-Chris Allinson
You can achieve this by two ways:
1- By using the following method:
**Put the following line in the -(void)viewDidLoad Method:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceRotated:) name:UIDeviceOrientationDidChangeNotification object:nil];
then put this method inside your class
-(void)deviceRotated:(NSNotification*)notification
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//Do your textField animation here
}
}
The above method will check the orientation when the device will be rotated
2- The second way is by inserting the following notification inside -(void)viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(checkRotation:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
then put the following method inside your class
-(void)checkRotation:(NSNotification*)notification
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//Do your textField animation here
}
}
The above method will check the orientation of the status bar of the ipad or iPhone and according to it you make do your animation in the required orientation.
For determining landscape vs portrait, there is a built-in function:
UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
BOOL inLandscape = UIDeviceOrientationIsLandscape(orientation);
[UIApplication sharedApplication].statusBarOrientation returns portrait when it's landscape, and landscape when it's portrait at launch, in iPad
I don't know why, but every time my app starts, the first 4 are right, but subsequently I get the opposite orientation. I use a static variable to count this, then have a BOOL to flip how I manually send this to subviews.
So while I'm not adding a new stand-alone answer, I'm saying use the above and keep this in mind. Note: I'm receiving the status bar orientation, as it's the only thing that gets called when the app starts and is "right enough" to help me move stuff.
The main problem with using this is the views being lazily loaded. Be sure to call the view property of your contained and subviews "Before" you set their positions in response to their orientation. Thank Apple for not crashing when we set variables that don't exist, forcing us to remember they break OO and force us to do it, too... gah, such an elegant system yet so broken! Seriously, I love Native, but it's just not good, encourages poor OO design. Not our fault, just reminding that your resize function might be working, but Apple's Way requires you load the view by use, not by creating and initializing it
In your view controller, get the read-only value of self.interfaceOrientation (the current orientation of the interface).
I've tried many of the above methods, but nothing seemed to work 100% for me.
My solution was to make an iVar called orientation of type UIInterfaceOrientation in the Root View Controller.
- (void)viewDidLoad {
[super viewDidLoad];
orientation = self.interfaceOrientation; // this is accurate in iOS 6 at this point but not iOS 5; iOS 5 always returns portrait on app launch through viewDidLoad and viewWillAppear no matter which technique you use.
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return YES;
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
orientation = toInterfaceOrientation;
}
Then, any place where you need to check the orientation you can do something like this:
if(UIInterfaceOrientationIsPortrait(orientation)){
// portrait
}else{
// landscape
}
There may still be a better way, but this seems to work 98% of the time (iOS5 notwithstanding) and isn't too hard. Note that iOS5 always launches iPad in portrait view, then sends a device the willRotateTo- and didRotateFromInterfaceOrientation: messages, so the value will still be inaccurate briefly.
[UIDevice currentDevice].orientation works great.
BUT!!!
... the trick is to add it to - (void)viewWillAppear:(BOOL)animated
exp:
(void)viewWillAppear:(BOOL)animated{
...
BOOL isLandscape = UIInterfaceOrientationIsLandscape(self.interfaceOrientation);
...
}
If you call it at - (void)viewDidLoad, it does not work reliable, especially if you use multiple threads (main UI thread, background thread to access massive external data, ...).
Comments:
1) Even if your app sets default orientation portrait, user can lock it at landscape. Thus setting the default is not really a solution to work around it.
2) There are other tasks like hiding the navigation bar, to be placed at viewWillAppear to make it work and at the same time prevent flickering. Same applies to other views like UITableView willDisplayCell -> use it to set cell.selected and cell.accessoryType.