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.
Related
I am building an application that must add an overlay view once a scrollview is done zooming. I was having problems adding the overlay to the scrollview itself and keeping the position consistent, due to what I assume is the scrollview not being done zooming...no biggie...so I decided to add the overlay to the sharedApplication's keyWindow.
Now, the application is in landscape orientation, and I have to do a transform on the overlay to get it to orient properly...this is fine. The issue arises in having to reposition the overlay by this seemingly arbitrary amount to get it centered...I dislike doing things ad hoc like this, so I thought I'd ask if anyone has run into something like this, and why the view has to be repositioned by this strange offset. Any insight would be great.
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI/2);
tempOverlay.view.transform = transform;
// Repositions and resizes the view.
CGRect contentRect = CGRectMake(-107, -80, 480, 320); //where does this offset come from?!?
tempOverlay.view.bounds = contentRect;
[[[UIApplication sharedApplication] keyWindow] addSubview:tempOverlay.view];
I was going to post this as a comment instead of an answer originally, but I'll just go for the answer route instead, even though I don't think there's really enough information to go on here. The following assumes that you have a fairly standard iOS application, aside from this overlay oddity where you're attaching the view to the keyWindow.
First, don't attach add your overlay view to the keyWindow. Instead, define some method on your root view controller which requests the overlay be displayed. Then in your root view controller code, add the overlay view to the controller's view above everything else.
Then, don't apply the transform since it will no longer be necessary to rotate your view.
At the time you create your view, set it's frame to be the bounds of the root controller's view. Also set it to have a flexible width and height via the autoresizingMask of UIView. Then assuming your root UIView has it's autoresizesSubview property set to YES, your overlay view will be nicely resized to match the size of the root view as it changes orientation.
If after all this the position of the contents of your overlay UIView is incorrect then I suspect the problem is within the contents of that UIView and has nothing to do with the need for any magic numbers in your frame/bounds.
NOTE: I haven't actually tried the above and am not 100% confident that in general your root UIView will enjoy having this extra overlay UIView thrown on top of it, on the other hand, it might remain blissfully unaware of it and everything will Just Work. Either way, to me it feels a lot less 'ad hoc' than what you're currently trying to do.
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...
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.
Is it possible to resize the UITableView on the RootController of a nav based app? When RootViewController.xib is opened in IB, there isn't a view. Just the UITableView. Clicking the inspector and then the little yellow ruler, frame height is grayed out. I'm adding a toolbar programmatically to the RootViewController:
[toolbar setFrame:rectArea];
That works fine but the bottom cell in the tableview is partially hidden because the tableview doesn't know about the toolbar.
The easiest way, is to adjust the contentInset (which is inherited from UIScrollView). Resizing by setting the frame can cause crazy drawing bugs in cells.
For example, if you are trying to resize a tableview for the keyboard, do something like this:
tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, 216.0, 0.0);
tableView.scrollIndicatorInsets = tableView.contentInset;
Hope that helps someone. This way worked best for me.
Yes, but you need to have a ViewController (not a UITableViewController) as the root controller for the nav, and wrap the actual UITableView in the UIViewControllers view.
You can still have the UIViewController conform to the UITableViewDelgate and Datasource protocols, and use all the same methods you have now in your UITableViewController.
P.S. you'll get more responses if you use the plain "iphone" tag.
You could also just set the Content and Scroller inset of the tableview
I encountered a similar issue when attempting to display the detail controller by itself, see: http://vimeo.com/13054813
The issue is that the SplitView controller applies its own transform to the sub-controllers, taking them out of the orientation detection loop, which blows goats and seems incredibly 'hackish' for built-in classes. (The video illustrates what happens when you make the detail view the root view, then add it back to the split view and make the split view root while in landscape; you get double rotation of the detail view.)
Unfortunately I've again run into these transformation issues while attempting to resize a SplitViewController's detail sub-view in response to the keyboard appearing/disappearing. In portrait, all works fine, in landscape it's fscked.
Yes, adjust the contentInset and scrollIndicatorInsets are the convenient way to resize the UITableView.
As the answer of Sam Soffes posted, I succeed resize UITableView in UITableViewController for the bottom UIToolbar.