I have setup a new iPad project to only support UIInterfaceOrientationLandscapeRight.
In my App Delegate I add a RootViewController to the window's rootViewController.
In this UIViewController (RootViewController) I have the following:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
I have also tried with:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
However, I am not able to get the correct dimensions for my app when I create and add subviews based on the dimensions of my view controller's view.
If I output self.view.frame for my view controller I get {{0, 0}, {768, 1024}}, but I would like {1024, 768} instead. If I can't when are the dimensions correct so I can create my views with them in mind?
Sorry if this has been asked a billion times, I've browsed lots of SO questions, but nothing has solved my issue.
I was running into the same issue, and what Ash Furrow said above seems to be correct; the orientation is set after viewDidLoad is called.
I was creating an iPad app that works in all orientations, but only the portrait orientations were getting set up correctly in my root UIViewController. In order to make the views layout correctly in landscape, I had to make sure the autoresizing masks on all my subviews was set to allow the view to adjust to landscape behind the scenes before being displayed to the user.
For example, I had a UIImageView that was the same size as the UIViewController's UIView. In order to get it to adjust correctly when rotating to landscape:
UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
backgroundImageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight);
[self.view addSubview:backgroundImageView];
Now the UIViewController can be configured in portrait orientation in the viewDidLoad method and rotate nicely to the portrait orientation before being displayed to the user.
EDIT:
Looks like the interface orientation is being set already in viewDidLoad
p (UIInterfaceOrientation)[self interfaceOrientation]
(UIInterfaceOrientation) $1 = UIInterfaceOrientationLandscapeRight
Here's my theory: interfaces on the iPad are, by default, 1024x768 if that have a status bar, which yours does. I believe that, even though the interface orientation is correct, it's not updating the view geometry until after viewDidLoad. I believe it has a very good reason for that.
If you look at the UIViewController Life Cycle docs, viewDidLoad is called as part of the set up of the view controller. After the view is loaded, willAnimateRotationToInterfaceOrientation: duration: is called to let your view controller know it's geometry is changing.
It's not so much an answer as an explanation. Hopefully this will help you architect a solution to get around this problem.
Begin answer that doesn't actually work:
In the info.plist for your project, open the "Supported Interface Orientations" option and delete the interface orientations you don't want to support. By default, all are supported:
That should clear it up.
I have a simple solution: the Apple default app templates work with XIBs for the main view controller. To solve your problem just open the main viewcontroller XIB and set orientation to "landscape".
As I usually don't use XIBs and create all UI elements programmatically. That's why I had the same problem in previous projects that really drove me crazy. I then solved it by hard-coding the frame width & height value - not the nice way.
Related
I am working on a landscape view for a currently existing application. I believe I have autoRotate, supported interface, etc set up correctly, I am actually reusing code that works with a much simpler app. However when the simulator is rotated into landscape mode, the correct view loads, but the status bar and view stay with the short edge of the iPad. I've attached a screenshot and code. Is the problem with a view controller higher up in the chain, or the appdelegate? I've traced the called controllers in the debugger and it appears they are dismissed once this page is loaded. I am fairly new-ish to obj-c so it is possible this is something simple I am missing, but I have checked all attributes for the .xib file and everything looks copasetic.
Some of the code:
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;// | UIInterfaceOrientationMaskPortraitUpsideDown;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return NO;
}![enter image description here][2]
-(void)orientationChanged{
UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if ((interfaceOrientation==UIInterfaceOrientationPortrait)||(interfaceOrientation ==UIInterfaceOrientationPortraitUpsideDown)){
self.view = self.portraitView;
} else {
self.view = self.landscapeView;
}
}
EDITS - This problem occurs on both iOS 7.1 and 6.1 and this is the first time any screen in the app supports a landscape view. To clarify the views, the portrait and landscape views are separate Views in single .xib file. The file owner class is set to the correct view controller class, and the parent view controller, a sales screen, should not rotate. It does not have a landscape view, but even with its autoRotate methods set to return YES the subview does not orient correctly.
Like 0x7ffffffff already said you need to allow rotation in your shouldAutorotate functions. Also you need to set up the supported rotation directions in your project setup.
First go to your project's settings:
Next you need to select all the orientations you want to support:
Another that is very important: ONLY the root View Controller will receive rotation events. If you nest a View Controller inside a View Controller then that nested Controller will not receive those events unless you wire them up manually from the parent. That's why I usually don't nest ViewControllers but use ad-hoc NSObjects or UIView implementations for nested views.
Last but not least: make sure your device is not rotation-locked: http://www.iphonefaq.org/archives/972915
The problem was occurring because a subclass of the customerView was not receiving the rotation notification. After tracking that class down it was a matter of setting up the NSNotificationCenter for orientation changes and then allowing autoRotation and supprotedInterfaceOrientations.
My viewController1 has a child view controller (viewController2). viewController2.view is a subview of viewController1's view. At the user's action, I remove the view of viewController2 from it's superview. After a while I have to add it again as subview.
The problem is that if the user rotates the device while viewController2 is not visible, after adding it again to viewController1's view, it's frame and it's subviews are placed as the device was still in the old orientation. Even the viewController2.view.frame has the height and with interchanged.
Does anyone have a solution to this? Thanks in advance!
Without seeing your code, I would guess that you are keeping a reference to view controller 2 even when it isn't visible. In that case, you need to forward the view rotation events to the controller so that it knows about the rotation like this (Do this for each event that you want to forward):
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Forward to view controller 2 if it is not displayed
if (!viewController2.view) {
[viewController2 willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
}
A better design may be to just set view controller 2's view to hidden instead of removing it, and it will still get the events without manual intervention.
Let me guess your problem. Do you want to show the different UIView base on orientation , right?
It's about update your viewController2 to load the nib base on orientation. You can make the landscape and portrait nib to support your different UI due to orientation. Try to look from this Answer
Hope it helps you
In an iOS5 application for iPhone 4/4s I have a UIViewController with an MPMoviePlayerController view added to its view:
[self.view insertSubview:self.fullscreenMoviePlayerController.view atIndex:2];
The UIViewController only supports landscape orientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation
{
// Return YES for supported orientations.
return interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight;
}
this correctly locks rotation to only landscape. However when I set the MPVideoPlayerController to display fullscreen, this is ignored and the video is no longer constrained to landscape and rotates to whatever orientation the phone is held in.
How can I prevent MPMoviePlayerController's video from rotating to Portrait orientations in fullscreen? It is crucial that the video does not rotate when the phone is rotated to portrait.
I have tried subclassing MPVideoPlayerController and overriding shouldAutorotateToInterfaceOrientation: but this has no effect.
The MPMoviePlayerController is only one part of the view, so using an MPMoviePlayerViewCotroller is absolutely not an option.
This seems to be rather difficult if you really want to avoid using MPMoviePlayerViewController.
One option, that seems to work even if you have it in fullscreen, is to manually set the frame of the MPMoviePlayerController's view.
(Note that in other iOS issues, sometimes using the background view has produced different results, but it's worth a shot).
MyMPMoviePlayerController.view.frame = CGRectMake(0, 0, your numbers, here);
However, Apple, in their docs, says that the controller's frame should be set to the frame of it's parent view.
[MyMPMoviePlayerController.view setFrame: parentView.bounds];
The less elegant solution, but one that might work even if that one doesn't is this:
Listen for the UIDeviceOrientationDidChangeNotification and take the movie player's view. Apply a transfrom, bounds, and center (or frame, etc) on it so that it still fits in the landscape view. Essentially transform it back each time it tries to rotate away. (This is all assuming that you really cannot keep it from rotating with shouldAutorotateToInterfaceOrientation:).
The only issue here is that it may keep the movie in portrait but screw around with the view, which is not the desired outcome.
yes, i saw you said using MPMoviePlayerViewController is not an option:
still … why not attempt to make MPMoviePlayerViewController of the ViewController that you have that otherwise contains the MPMoviePlayerController and the other items in your view controller. the good part about this is that MPMoviePlayerViewController already has the MPMoviePlayerController built in. you just refer to that instead of the MPMoviePlayerController that you have in your own viewController. that has the shouldAutorotateToInterfaceOrientation that you can override and should do the right thing for you.
You can prepare two videos. If there is no other choice.
Please Visit the link this shows the video only in the landscape mode by default it does so http://mobiledevelopertips.com/video/getting-mpmovieplayercontroller-to-cooperate-with-ios4-3-2-ipad-and-earlier-versions-of-iphone-sdk.html. I hope it will resolve your problem.
I have an app with an UITableView at the home screen. I made this view to always be in landscape orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
If the user picks a row he will be taken to a UIPageViewController view. This second view can rotate to landscape and portrait. The problem is when I am in portrait mode on the UIPageViewController and I press the go back button, the first view which is supposed to be always in landscape mode now is in portrait. After I rotate it, it gets into landscape and stays there.
I was wondering maybe if there is a way to make my home screen go automatically into landscape when I go back to it.
Try the following
Create the view of your main screen in app in interface builder in Landscape mode.
Create uiview oultlet in interface class and connect it to above view.
IBOutlet UIVIew *myView;
Then in the viewDidLoad method set this
self.view = self.myView;
If you want to make a screen in a particular orientation then you can create a CustomNavigation controller and then present it in your app. You have to only return supportedInterfaceOrientations in this. If you want more detail and sample code click here.
Call shouldAutorotateToInterfaceOrientation manually when you go back. You can not force a "real" orientation change, that's a OS thing.
As said in the view controller programming guide, you can have a alternate landscape interface and before coming to home screen from any other view, you can check the orientation and push the corresponding interface onto the screen
Read this SO question and answer for better understanding of launching an app in landscape.Also go through above apple programming guide which i pointed to.
If you use the UINavigationViewController methods(pushViewController:animated: and popViewControllerAnimated:), the views will inherit the previous view's orientation.
On the other hand, if you use presentModalViewController:animated: and dismissModalViewControllerAnimated: methods, everything works perfectly. Hope this helped!
Use this, change the UIInterfaceOrientationLandscapeLeft to required orientation type as UIDeviceOrientationPortrait, UIDeviceOrientationLandscapeLeft etc.
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
I am creating an application with Landscape Right orientation. For that I set the Initial interface orientation property in info.plist file. Then in every view I handled
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return(interfaceOrientation==UIInterfaceOrientationLandscapeRight);
}
It works fine in simulator but in device its behave differently.
My first view is in proper orientation. There is is popover which display another view that comes in portrait mode. Still my status bar is in Landscape Right..
For navigating from one view to another view I am using..
self.window.rootViewController = self.myNav;
I have multiple navigation Controller and adding those using the upper code.
I am not getting what is the problem.
Any help will be appreciated.
EDIT: I had used
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
I never get this issue in simulator but getting this in device and not every time. I have used Supported interface orientations (iPad) too and set Landscape (right home button) value for item0.
Thanks In advance
You need to set the "Simulated Metrics > Orientation" property of your top view (in all your xib files) to be "Landscape". The default is portrait.
The question was answered pretty well here - Landscape Mode ONLY for iPhone or iPad .
I also have an app that like yours only supports UIInterfaceOrientationLandscapeRight. I haven't run into any orientation issues so far. I only have one UIViewController under the window. This UIViewController has its own UITabBar that I use to change pages. So, we change pages differently. I set my UIViewController using the rootViewController property of the window just like you, but again I only have one.
Also, I never had to do anything like the [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications] call that you included. Since you only support LandscapeRight orientation, you shouldn't care to be notified of changes.
EDIT
I created a sample project, which I can post if necessary, and I think I may know your problem. First - do you only encounter the sizing issue inside popovers? If so, then I don't think orientation is throwing you off but the popover itself. My sample project has 3 view controllers. The first loads the second by changing the window's rootViewController. That worked fine. The second view controller has a button to open a popover. This will show up wrong unless you set the contentSizeForPopover on the view controller as shown below:
- (IBAction) showVC3InPopover
{
UIViewController * vc3 = [[VC3 alloc] init];
/** Set the contentSizeForViewInPopover property to determine how
large the view will be in the popover! You can do this in the
init method(s) of the view controller if you prefer, it's just
easy to do here */
vc3.contentSizeForViewInPopover = vc3.view.frame.size;
[_popover release], _popover = nil;
_popover = [[UIPopoverController alloc] initWithContentViewController:vc3];
[vc3 release];
[_popover presentPopoverFromRect:_showPopoverButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
See if this fixes your problem. If it does, there are other ways to control the popover size, but this is just what I typically do. However, just know that the PopoverController ignores the size of the view in the viewcontroller you load.
How many views (or viewControllers) you have? You might need to implement this orientation logic in all those views??