I have a root view controller that will have up to 10 or so subviews.
I am implementing autorotation/autosize accross the entire app.
My problem is this:
- When I allocate all the view controllers and add each as a subview to the root controller during startup, everything works as it should. The only problem is that each view controller needs time to initialize. This causes my application to load very slowly.
Instead I am trying to allocate the view controllers as they are required. Now I find that if the application goes into Landscape, and I allocate a view controller that is designed in portrait, it will autorotate but the autosize doesnt happen.
In other words as soon as the subview is added to the root controller in portrait mode it rotates and sizes correctly (and stays that way). If the subview is added when the root controller is in landscape it rotates but doesnt autosize (and view sizes remain messed up rotating back to portrait)
I have tried to force an autosize by calling SetNeedsLayout, SetNeedsDisplay, and LayoutIfNeeded but nothing works. I know i could probably do this manually by determining the root controllers orientation and resizing the subviews appropriately, but this is a lot of work for something that should work automatically.
Am I missing something? Any help would be appreciated. My project is an iPad port from an iPhone app, the iPhone app doesnt rotate so Im not sure if this may be something wrong with the 3.2 beta.
After wrestling with this for a while I added the following code to my subview. It executes after the view is added to the root view controller. So far it seems to work.
-
(void) AdjustFrame{
UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if((interfaceOrientation == UIInterfaceOrientationLandscapeLeft)||(interfaceOrientation == UIInterfaceOrientationLandscapeRight))
{
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
CGRect newFrame = CGRectMake(0.0, 0.0, applicationFrame.size.height, applicationFrame.size.width);
[self.view setFrame:newFrame];
[self.view setNeedsDisplay];
}
}
Related
I have an iPad app that is set to start in landscape mode.
From what I read, the UIWindow itself doesn't need to be rotated, instead it will apply a rotation transform to all of it's subviews when the device is rotated.
My application has a UINavigationController which has the app's views, and above it a custom MenuBarViewController which will show sometimes on one edge of the screen.
In my app delegate's didFinishLaunching.. I do:
[window addSubview:navigationController.view];
[window addSubview:menuBarWrapperViewController.view];
[window bringSubviewToFront:menuBarWrapperViewController.view];
The views within my navigationController seem to be fine, however the view in my MenuBarViewController are not rotated.
I've checked, and both my MenuBarViewController and my MenuBarWrapperViewController (which doesn't do anything yet) return YES to shouldAutorotate..
Does anyone have any idea why one of my UIViews subviews doesn't get the correct rotation transform?
EDIT: upon further investigation, it seems that UIWindow only applies the transform to the first added subview, so if I change the order of addSubview calls, only the first subview will be rotated.
Does anyone know why?
Perhaps you should try having one view controller be in charge of handling all rotations of all subviews being displayed.
In my iPhone app, I have a UIViewController with two subviews: a main UIView (let's call it mainView), and a secondary UIView (let's call it secondView), which is usually hidden but is sometimes shown (e.g. user settings). In my UIViewController, self.view is set to mainView. When the user switches to the subview, I call [self.view addSubview:secondView] and when the user switches back to the main UIView, I call [secondView removeFromSuperview].
There are two issues which I am dealing with at present:
When the user rotates the iPhone or iPad, the main UIView (mainView) autorotates properly and all of its UI items follow its autoresize rules which I have set up in Interface Builder. However, when the secondary UIView (secondView) is displayed, and the iPhone or iPad is rotated, the secondView & all of its UI items do not follow their autoresize rules. I have found that when I set self.view = secondView, and then rotate the device, the view rotates properly.
In the iPad specifically, when I pull up the secondView using [self.view addSubview:secondView], it is not resized to fill the full screen just as the main UIView has been resized for the iPad version. So I end up with a screen that displays the mainView UIView in the background, and the secondView UIView in the top-left corner without taking up the whole screen.
My instinct tells me that these two issues are related to one another. Has anyone else experienced these kinds of issues with secondary UIViews which they add to their UIViewControllers using addSubview:?
When using addSubview,
[secondView setFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
Not very elegant. But it worked for me:
I had a similar problem. I solved the size issue by setting the content mode of the view.
Exp:[_yourView setContentMode:UIViewContentModeScaleAspectFill];
I hope this helps...
In my iPhone app, I have a view controller with two views (essentially, a front & back view). The front view is the main UIView, and the back view is a secondary UIView which is added as a subview using [self.view addSubview:backView] when showing the back and [backView removeFromSuperview] when hiding it. However, when the orientation changes, I have the following issue: the main UIView (frontView) rotates & all of its elements resize properly, but the secondary/subview UIView (backView) does not rotate & all of its elements do not resize properly. Does anyone have suggestions on how to make the secondary UIView autoresize properly according to the rules I have set in Interface Builder?
In the end, the solution I found was simply to separate my UIViews into separate UIViewControllers, and make sure that any views that I wanted to be able to rotate only had one UIView.
If I understand correctly, at the time of rotation 'backView' has been removed from it's superview, yeah? If so, that's the cause of the problem. The autoresize property determines how the view resizes relative to it's superview. If it doesn't have a superview it won't resize.
Perhaps using [backView setHidden:YES] instead of [backView removeFromSuperview] will be sufficient for your needs.
I had the same problem, here is how I fixed it based on imaginaryboy's
suggestions (thanks!)
Add the backview to the viewcontroller at viewDidLoad and hide it at the same time. Show it when needed, Hide it again. Set the resizing of the backview to UIViewAutoresizingFlexibleWidth in IB (or code I guess, I used IB)
Not that this is the same problem, but I found a similar problem when adding 2 subviews in my application:didFinishLaunchingWithOptions method. Since your reference above is using [self.view addSubview:view], I would understand that to mean that self is not your UIWindow. When adding an additional view controller to your App Delegate window (UIWindow), the second view controller will NOT receive any rotation events and will never rotate. Only the first view controller added to UIWindow will rotate. See:Technical Q&A QA1688 I believe this also affects views added after the first view where the first view is later removed from the superview.
I ended up following the suggestion I read elsewhere to use separate views for each orientation, thereby eliminating the need to worry about resizing behavior. As always, YMMV.
Or; if you want to avoid an additional controller, you can achieve the same effect by setting view.frame in willRotateToInterfaceOrientation:: like so
if(UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) ;//set stubborn view.frame for landscape orientation
else ; //set stubborn view.frame for portrait orientation
Although it feels like a hack; it's simple.
i have a iphone sdk orientation issue...
i push a "holding" view controller onto the navigationController. The holdingViewController uses viewDidLoad to show the navigationController navbar and add a flip button to it and a selector for the flipbutton. it then adds a subview using UIViewAnimationTransitionNone showing a UIView containing a TableView. When the flip button is clicked the holding view controller removes the loaded subview and replaces with the another subview, also containing a view with a tableview, and transforms using the flip animation. The problem comes when flipping and changing orientations. although both flipping and rotating appear to work at first if i flip while in landscape mode, the flipped view is sort of "cropped" to portrait width, although actually displayed in landscape, rotation then doesnt fix it, u have to flip back, rotate back to portrait, then flip back again. It looks like the holdingview is not registering the change in orientation, but i know it is as i've implemented
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
on all 3 view controllers and i can see orientationChanged function being called for each.
All three viewcontrollers are setting autoresizing in viewDidLoad
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
and i've also implemented
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
does anybody have any ideas whats going on, or more importantly, what i can do to fix it?
many thanks
I had a similar problem with adding a subview. The subview was being cropped while in landscape orientation. I had to set the frame of the subview before adding it so that the subview would fill correctly.
Here is the code that fixed my issue: [subcontroller.view setFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
My statusbar orientation is landscape, I have a cocos2d view that only supports portrait orientation(it is OK since it handles transformations). I have another view that is presented as a modal by cocos2d controller, its orientation is landscape, but whenever I dismiss it, my statusbar orientation somehow changes to portrait, I tried overriding supported orientation methods of container views, but none of them has any effect.
regards
OK, here is how I did it, I thought what messes things up is the fact that orientation of container being different from the view that is presented as modal. So I added another view to contain cocos2d view and presented the modal using that view. The container's orientation is lanscape, so I needed to transform cocos2d view int he load method of its controller.
self.view.transform = CGAffineTransformRotate(self.view.transform, -(M_PI / 2.0));
self.view.frame = CGRectMake(0, 0, 480, 320);
I am still looking for a better way of doing this.