Here's what I'm trying to do.
I have a single view ("primaryView"), controlled by a customized view controller. primaryView contains a scrollview, which contains an image. Sitting on top of the scroll view (NOT inside it) is a small view ("buttonsView") containing a few buttons.
Basically, when the user rotates the phone, I want buttonsView to autorotate to match the new orientation, but I want the scrollview to remain exactly as it is, and NOT rotate.
Is there a way to do this? Right now, primaryView is autorotating, and taking both subviews (the scrollview and buttonsView) with it, which is no good.
Thanks!
The system will not autorotate unless all visible views consent to autorotation. What you can do, then, is to detect orientation changes, and set an appropriate affine transform for the non-rotating views, essentially to undo the system's rotation.
You can use willRotateToInterfaceOrientation:duration: to fade out the controls, then didRotateFromInterfaceOrientation: to fade them back in at the correct location.
Related
I have an app that allows a user to drag views onto the screen in multiple orientations. So lets say i'm in portrait mode and my superview is 768x1024. Lets say I drag 10 different items onto that superview. These items are scaled, rotated, etc. Then I rotate the device and my superview shrinks down to 576x768. How do I get all of my subviews to maintain their position and transform relative to the new smaller size? So in essence my superview and all of its subviews should look exactly as they did while in portrait, except everything has been scaled down.
And also, what if im in landscape and everything is "shrunk" down and then I drag another view on and shrink it down to fit well. I would need that new view to scale up in proper place and size when the device is rotated back into portrait
The easiest thing to do here is to use the transform property of your view. In this case, you'd prevent the view from auto-resizing on rotation, and use something like your view controller's willAnimateRotationToInterfaceOrientation:duration: method to set a transform on your superview. You can create a transform with CGAffineTransformMakeScale that will scale up or down all of your content; you'll probably want one for landscape and just use a nil transform for portrait (or vice-versa).
This will complicate dragging new views into your superview, since it's transformed, but once you've got views in there, they should behave correctly when resizing. For new views, you'll have to compute (perhaps using convertRect:fromView: method of UIView) what a rect will be once you add a new subview.
You can also override your view's layoutSubviews() directly and assign your subview's transforms based on your view's dimension. This way, you can still get the benefits of using Auto Layout with your view and potentially other sibling UI items, while you customize subview's frames and/or transforms manually without Auto Layout.
I have a simple 1 screen app, with 1 View.. the view contains
a button, an textbox and a button across the top
A segmented controller across the bottom
and a MapView in between.
In portrait mode all is right with the world.. So I decided to begin to allow Orientation change...
in IB all views and elements and even the root window have autoResizeSubviews set
in My AppDelegate and my viewController I have also programatically added SetAutoResizeSubviews to yes explicitely I have set the autoResizingMask in the Root Window and the View Controller to FlexibleWidht | Flexibile Height
I have added the shouldAutorotateToInterfaceOrientation in my ViewController to always return true.
Yet, it doesn't work.. Or should I say it doesn't rotate properly.. in both portrait modes everything looks great, but both landscape modes, things don't get laid out or resized properly.. Basically all I see is the mapview, and its size gets slightly wider, but not much than the portrait mode, and it doesn't fill up the screen top to bottom.. all other interface elements with the exception of one button are invisible and it appears on TOP of the mapview.. as thought it just happened to be layed out over the view by coincidence than any design.
Anyone have any ideas what I am missing, or why?
Thanks in advance
You say "I have set the autoResizingMask in the Root Window and the View Controller" but that is a red herring. It is the buttons, the text box, the segmented controller, and the map view that have to have the correct autoresizingMask. If this view is being designed in the nib, you can set the values there and then turn the orientation right there in the nib and see what happens.
If you are unable to work out good autoresizingMask values for all those interface elements, implement didRotateFromInterfaceOrientation and perform the layout alterations in code when called upon to do so.
I'm using Apple's sample code for having separate Portrait and Landscape view controllers (presenting/dismissing a modal view controller from within the orientationChanged method). However, it creates a number of problems:
The status bar doesn't rotate. If I manually setStatusBarOrientation, I get very strange behavior.
The transition is very abrupt; I prefer
the conventional smooth animation,
especially because...
90% of the
view changes, but there are two
images which should look exactly the
same (same size, same position, same
orientation) in both the landscape
and portrait modes.
My goal is a rotation transition more like the one in the Stocks app. How can I achieve this?
Thanks.
You could use core animation to do that. Fade out all elements that don't appear in the other view (by animating the opacity). Move and rotate the objects that are the same in each view. And finally fade in new objects in the second view. It might get rather complicated, depending on the complexity of your view. Have a look at these methods to find out where to implement the animations:
– willRotateToInterfaceOrientation:duration:
– willAnimateRotationToInterfaceOrientation:duration:
– willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
– didAnimateFirstHalfOfRotationToInterfaceOrientation:
– willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
I have a view based app. Its self.view has several subviews and shouldAutorotateToInterfaceOrientation is returning YES.
When I rotate the device, all views rotate as expected.
Is that possible to prevent a subview from auto rotating even if the view's parent is auto rotating?
Keep in mind that it's the view controller that controls what happens during rotation and not the view itself. You can't stop a subview from rotating by setting a property, or something relatively easy, if its parent view's UIViewController is set to auto rotate. You can, however, have sibling views where one rotates and the other doesn't. It's probably possible to layout your views the way you want but not have the one that shouldn't rotate as a subview of a rotating UIViewController.
You could probably write some code that will reorient a subview so it appears not to rotate when the parent view does rotate, however.
I have been reading a ton on rotation, but not finding a solution to my query. Here goes:
I have a portrait application with a tabbar and hidden navigation controller in my tab. At a point in the app, the next view must be landscape.
The XIB layout has been done in landscape, so I want to bring up the xib without any translation or pixel moving code. (not thinking this is required) I have tried just pushing the view (remains in portrait), shifting the view using various methods (non seem to line thing up properly).
Is there a way to tell the view that it is already laid out for landscape prior to it being opened?
Thanks in advance!
Found it, this code does the trick in the viewdidload:
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 460.0, 320.0);
Still have 1 odd thing. No matter what I do to set the navigation bar to hidden, it does not rotate, and stays at the left side of the view.
[[self navigationController] setNavigationBarHidden:YES animated:NO];
Has anyone seed this behavior and solved?
I'm positive that you cannot 'force' a rotation. The system decides when to change the orientation of the device; so the 'orientation' properties are essentially read-only. I looked into this same problem a long time ago when I wanted to make sure a particular view always displayed in one orientation.
Due to this, most apps allow all of their views and view controllers to work in any of the orientations the app supports. I've found that trying to restrict the behavior of some views and view controllers ultimately creates more hassle, and can cause issues when transitioning between views and view controllers.
The code you posted will work for your view. You are not actually changing the orientation at all; your view is just behaving like it has been rotated by drawing in a rotated fashion. I'm not sure if you can do the same thing to the navigation bar or not, but it's worth a shot. If you are able to control the view properties of the navigation bar (it is a UIView as well), applying the same pattern you are using for your custom view should work.
Most apps that want a view to only be in landscape ultimately force their entire app to be in landscape. For instance, Flight Control only supports one orientation. Thus, the drawing code is pretty simple; regardless of orientation, just draw the view and rotate it to the one orientation it supports (either landscape left or right).
Your app's design wouldn't be that easy... it sounds like you are not designing a full-screen app. You would have to worry about the navigation bar and status bar being properly drawn.