I've created a custom UIViewController that mimics the UISplitViewController. It manages two child view controllers that get displayed in the left & right body area while in landscape and hides the left to show in a popover when in portrait. It works fine, using the didRotateFromInterfaceOrientation: and willRotateToInterfaceOrientation: messages to reset the location and sizing of the child views. All the views and child controllers are loaded from a nib. This custom view controller is shown inside a UINavigationController.
The trouble arises after one of the child view controllers uses presentModalViewController. If the device was rotated after the views were initialized (but before the modal controller is shown), after the modal dialog is dismissed, the left and/or body views will be re-rendered in a different rotation than they were before the modal dialog was changed.
I'm wondering if folks have had a similar problem, and what the solution is. I'm sure sample code would be helpful, but it'll take a bunch of work to distill it into a runnable sample.
When I saw this same behavior in my split view app, I noticed that it only happens when I'm holding the device in "left home button" landscape. I had set my initial interface orientation to "right home button" but was allowing either left or right home button landscape orientations (no portrait orientation for this app). My solution was to no longer support left home button landscape orientation and now all post-modal subviews display reliably.
Related
I have an OpenGL app which supports dynamic device orientation. I can rotate the device to any of the 4 physical orientations and everything works as expected.
Now I've added a modal view controller so that you can get a settings view (this is non-OpenGL). The modal view controller also supports any device orientation.
However, if I present the modal view controller in orientation A (e.g. portrait) and dismiss it in orientation B (e.g. landscape-right), after it is dimissed, the OpenGL view is corrupted (the aspect ratio looks wrong). I have to orient the device to a different orientation for the OpenGL view to 'correct' itself.
When the modal view controller is dismissed, it's like the app thinks that it's already in orientation B, so it doesn't ever rotate the OpenGL view.
If I disable rotation on the modal view controller, then if I present the modal controller in orientation A, rotate the device to orientation B (the modal view controller no longer rotates) and dismiss the controller, the OpenGL view gets willRotateToInterfaceOrientation/didRotateFromInterfaceOrientation and correctly orients to orientation B.
Is there any way to preserve the dynamic orientation of the modal controller, yet have the OpenGL view also properly rotate after the modal controller is dismissed?
Thank you.
I had a similar issue with a custom action sheet, and decided that the simplest answer would be to temporarily disallow rotation while the view is presented. You can see an example of this in the Apple Notes app, whenever an action sheet is presented the orientation becomes locked.
I know you've already tried this and it works, I just think you should consider that as a valid solution.
I'm not sure how to solve it otherwise, you would probably need to store any changes in orientation in your modal view controller and pass them back to the OpenGL view controller, either at the same time or once at the point of dismissing the settings view, then manually re-render.
I've got an app that has two parts. Basically, the first part shows a bunch of image thumbnails. When you tap an image thumbnail, a full view of that image pops up inside a UIScrollView, filling the screen, with some buttons on top of it for performing various actions.
I want the main page with the thumbnails to always be in Portrait mode. But I want the two subviews -- the scrollview containing the image, and the uiview containing the buttons -- to autorotate when the user switches orientations.
I've tried having the View Controller for the main view return NO for the shouldAutorotateToInterfaceOrientation method, and then having the two subviews' controllers return YES, but then NOTHING rotates.
Is it possible to have only those two subviews respond to rotation events? How?
How are you presenting the scroll view and buttons? Strictly speaking, they should be managed by the same controller, presented modally over your first view controller. The autorotation system relies on whatever it thinks is the "main" view controller, which, in this case—assuming you're not actually using -presentModalViewController:animated:, as it doesn't sound like you are—remains the controller that's displaying the thumbnails.
In other words: have one view controller set up the scroll view containing the full image and the action buttons, and, when the user taps a thumbnail in the main view, present that view controller.
I think you can register as an observer for this notification, UIApplicationWillChangeStatusBarOrientationNotification
This notification is in the UIApplication Class Reference.
When the application is about to change the orientation of its interface, the notification is posted.
I am facing few problems while using tabBar with navigation controllers.Each tabBar item is associated with a separate navigation controller.Problems are listed as follows:
1.There are more than five tabBar items in my tabBar so a more tabBar item comes by default.Now when i tap the more tabBar item the remaining items come in a tableview which is actually the view of a navigation controller(which comes by default).Now when i select any of the row, my new view controller gets pushed into that navigation controller.I want my view controller to be the navigation controller.So there is a situation like pushing a navigation controller onto the sack of another navigation controller.The compiler gets confused and it does nothing.
2.Although I have set autoresizing of each controller of tab bar controller nothing happens on rotating the device.However when I keep only five or less tabBar items,autoresizing works perfectly.
3.I want an ImagView at the top throughout the application, so I attached an imageview on the window itself and than increases the y-coordinate of the tabBar controller's view so that the navigation bar of each tabBar controller's view starts just below the imageview.Everything is fine for the portrait mode but as soon as i rotate the device the imageview dissappears.And when i again come to portrait mode the imageview does not appear and the tabBar controller's view starts from the top.
I tried it every ways(like tabBar instead of tabBar controller etc.) but fail to achieve anything helpful.
I've never heard of that problem before. Can you paste some code? Also, are you sure that the tabs on the view more page work correctly?
In order for a TBC to rotate, all of the root view controllers of each tab must support rotation. In each of those files make sure shouldRotateToInterfaceOrientation: returns YES for all orientations (if you're using the default iPhone VC template take out the if(interfaceOrientation == UIInterfaceOrientationPortrait) statement and associated brackets).
I've actually done this before, and trust me when I say you're opening up a can of worms. To achieve this you need to add the TBC as a subview of a view that has an imageview on top. You must manually set the TBC.view frame to not cover up the top image. The best way to do this is: in the .xib for the container file, add an image view up top, and under it another view. Connect the view to the code via an IBOutlet, and set that frame as the TBC.view.frame. Then add the TBC.view as a subview programmatically.
With this solution, however, you must add in a willRotateToInterfaceOrientation:duration: method that calls the same function in all the TBC's viewcontrollers, and all of those viewcontrollers must be navigation delegates that call viewWillAppear: and viewDisappear: manually. The rotation is also a bit "sticky" when you do this, so beware.
My suggestion: don't put a static image up top. It causes a lot of issues, and takes up a lot of screen real estate, especially on the iPhone's smaller screen. Look at The Weather Channel app if you want to see how bad it looks.
Let me know if you have any more questions!
I have a UITabBar/UINavigation application and I'm having some trouble allowing autorotation in a given view.
The TabBar allows changing sections, with table view items. When one of the items is tapped, I push a new view which hides the TabBar and which should autorotate. I tried the easy way, which seemed most logical to me: disable autorotate in the rootViewController and allow in the detailViewController, but this didn't work (shouldAutorotateToInterfaceOrientation returns YES, but then willRotateToInterfaceOrientation is never called and view doesn't autorotate). I read that all VCs in a TabBar should return YES to shouldAutorotateToInterfaceOrientation, so I did that, but the result is that now my whole application rotates.
I then subclassed my UINavigationController and set shouldAutorotate to NO, hoping that I could detect when the view that was being shown was in fact a detailView, and then return YES... I can't seem to do that.
Any help out there?
Thanks!
Antonio
It sounds like you've got a set up like the iPod app which has a tabbar for playlist view, songs view etc but which disappears when you go to a detail view for a song. The detail view can rotate but the tabbar views do not. When you do rotate the tabbar it turns into a cover flow detail view.
I'm pretty sure they do this by putting the tabbar inside a navigation controller. When you go to the detail view, it pops the tabbar entirely and pushes the detail view.
So the actual hierarchy looks something like:
Nav {
tabbar {
playlist
Artist
//... other tabs
}
detail view portrait
detail view cover flow
}
Only one of the sibling views (tabbar, detail portrait, detail coverflow) is pushed at any one time.
The iPod app does this because the detail view is the primary functional view for the entire app so the rest of the app is built around navigating to it. If that is not the case for your app, then this setup may be more trouble than it is worth.
(By the way I develop without Interface Builder)
If you have a tab bar app that autorotates, so all the autoresizing masks are set, how do you make it work with all the views? Like if one view autorotates to landscape, you select a different tab in the tab bar, and the view associated with that tab comes up, and its all messed because it never got autorotated, it got initialized with the frame that makes it fit in portrait mode, even though the autoresizingmasks are set to have it look fine in landscape, it never got rotated. Whats the solution? (By the way, I'm lazy loading the views, so the only view loaded at any given time is the view(view controller's view) associated with the selected tab).
Does declaring all the required orientations in the didrotatefrominterfaceorientation method in every view controller you are using fix the problem?
e.g. your main view, with the tab bar is called "mainView", and when you choose a tab, it loads a view called "firstView", does the "firstView" view controller have the orientations set?
If a view controller is not loaded, it won't be able to respond to autorotation messages. So in your view controller, when it's loaded from the nib, it should check the orientation and resize and move things as necessary.