iphone sdk subview/superview orientation problem - iphone

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)];

Related

Cocoa-Touch: UIWindow not rotating some subviews

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.

UIView subview is not autorotating or auto-sizing for iPad

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...

UIView Subview Does not autoresize on orientation change

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.

How do I initialize a view to an interface orientation?

The problem is that I am launching in-app email and triggering keyboards (via UITextFields) and they are coming up portrait on my landscape app. I am able to rotate it portrait, then rotate it landscape again, observing the black rotation corners animation that occurs when an app rotates from portrait to landscape. Since I've locked out any orientation but landscape right in my shouldAutorotateToInterfaceOrientation() method, the view itself doesn't rotate, which is great. However, when I add these views, the app keeps thinking they are portrait as is evidenced by the UITextField keyboard and in-app email orientation unless I rotate to portrait, then back to landscape (which triggers the autorotate method to return true.
Any suggestions on how I can make this app know it's already in landscape to begin with when I'm adding views?
Update: I had tried setting the status bar orientation, but it does not work for me. I don't know if there's something with the fact that I remove and then add views to the app that is confusing its understanding of the orientation. Do you know how apple objects such as the UITextField and in-app mail determine what orientation to show? Do they simply poll the sharedApplication orientation? The odd thing for me is that it seems like when I remove and add new views, these apple widgets that I've tilted the phone to change to landscape suddenly revert to showing as portrait. i.e. this general sequence of events:
1) app in landscape, trigger keyboard, it shows portrait
2) tilt device to make it go into landscape. close and open keyboard and it's in landscape.
3) remove and add some views.
4) trigger keyboard again, it shows up in portrait
[UIApplication setStatusBarOrientation:animated:] should give you what you want.
Setup Initial interface orientation field in Project plist
Interestingly, I found that setting the status bar orientation at the launch was not enough. Watching the field value, I noticed it was resetting to portrait at various times, such as when returning from canceling an in-app mail. I found making multiple calls to set the status bar seems to address the problem. Thanks for the input, mbehan.
Removing/adding views shouldn't change the status bar orientation; as far as I know, that defaults to the view controller's orientation unless you set it explicitly (and then you have to be careful, because view controllers reset it). You can try using UIStatusBarStyleBlackTranslucent and setting UIViewController.wantsFullScreenLayout on your VCs to see what's going on.
(In the past, I've noticed it getting confused when I add a view to the window directly, on top of a portrait-only view. It seems to work in all other cases though...)
What's your implementation(s) of shouldAutorotateToInterfaceOrientation:?
try this:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//Rotate the complete view to look like landscape view
[self rotateToLandscape];
}
and the rotation method;
-(void)rotateToLandscape
{
UIWindow *win = [[UIApplication sharedApplication]keyWindow];
if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
[[[UIApplication sharedApplication] keyWindow] setBackgroundColor:[UIColor blackColor]];
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
win.transform = CGAffineTransformIdentity;
win.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
win.bounds = CGRectMake(0.0f, 0.0f, 480, 320);
win.center = CGPointMake(160.0f, 240.0f);
[UIView commitAnimations];
}
}

Subview Doesnt AutoSize When Added to Root View Controller

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];
}
}