I've checked the other answers but have not found anything that really describes my situation. So here goes.
I have a window-based app that creates and loads a UIViewController from xib. It has status bar disabled, height of 480 and a UISegmentedControl with y origin of 451. It displays nicely at the bottom of the screen.*
In viewDidLoad of the UIViewController I create a UIView initWithFrame:CGRectMake(0.0, 0.0, 320.0, 431.0)]; (that's 480 - 29 pixels for the UISegmentedControl and 20 for the status bar.) I add it to the UIViewController with [self.view addSubview:gameBoard];. Then some UIView game pieces are added as subviews of the gameboard UIView and everything is displayed as I think it should be.
When some of those UIView subviews are tapped, a menu should appear. I have created a UIViewController with the required controls on it. I use a delegate method to call from the subviews, who pick up the triggering events, to the root UIViewController - which does
self.squadOrders = [[SquadOrders alloc] initWithNibName:#"SquadOrders" bundle:nil];
squadOrders.viewControllerDelegate = self;
[self presentModalViewController:squadOrders animated:YES];
And the modal dialog displays as I think it should, sliding up from the lower edge of the screen, not covering the status bar but covering the UISegmentedControl mentioned at the bottom of the root UIViewController. It gets dismissed by
[self dismissModalViewControllerAnimated:YES];
and that's where the trouble begins. The UISegmented control is moved down by 20 pixels so that only 9 pixels of it is visible at the bottom of the screen. There is a 20 pixel white gap at the top where the view has been moved down.
*enabling the status bar on this or any other xib does not change the described behavior at all.
Other stackoverflow questions related are:
IPhone - After dismissing Modal View Controller - gap is left at top of page - but the given solution was don't have another view controller loaded as a subview of the view controller that displays the modal - but I don't, only UIViews. There's also the suggestion of just resetting the appropriate frame after the modal goes away but it feels like cheating.
Contents of UIScrollView shifted after dismissing ModalViewController - I've played with the heights of all the views and controllers - am sure they match, hasn't helped. Again, the frame can be reset but it only addresses the symptom.
There are others but nothing is solving this issue so far.
I've just solved this issue with view shifting down.
It was because of navigationBar.barStyle set to UIBarStyleBlackTranslucent.
This is a hack, but might help somebody. I was having plenty of these 20 pixel gap issues throughout my app and they all went away by using a navigation controller as my root view controller. I don't really use it as a nav controller at all (and I hide the nav bar), so this solution can work in most apps.
Basically, I have a BaseView (320 x 480, no status bar) whose controller sits in my nav controller, and then the rest of my app is added as subviews to the BaseView. It all works great now.
Related
I have three viewcontrollers all in a navigation stack. The first view controller does not utilize the uitoolbar, the second one does and the third one does not.
The problem is, when I go from the second UIViewController to the third UITableViewController, if I hide the toolbar, there is a white gap at the top of the screen.
Here's a picture:
I currently have [self.navigationController setToolbarHidden:YES animated:YES];
in the viewWillDisappear of the second view controller, but I've also put it in the third view controller's viewWillAppear method. Both cause the gap to appear.
How can I fix this?
First off, I'd recommend using setToolbarHidden:YES animated:NO to have the new UIViewController appear without the toolbar. I think your method will show it initially and then it disappears, right? If you use the animated:NO (or else use the method signature without animated:), the new UIViewController should "push" off the UIToolbar for the 2nd UIViewController when the 3rd UIViewController is pushed onto the screen.
Secondly, you probably need to have a look at your shocks and struts for your UIViewController's view in Interface Builder. That is almost certainly what's causing this gap. You probably want to have a fixed top and bottom margin and a flexible height.
I'll answer my own question, but I'm not going to accept it because it is hacky.
I was able to fix it by adding this line of code at the beginning of viewDidLoad:
[self.tableView setFrame: CGRectMake(0, 0, 320, 493)];
Basically, I set the tableview frame's height to be 13 pixels bigger than the size of a full screen (which is 320 x 480).
I've been trying to add a UIView (with a UIImageView) as an initial screen when the user launches my application for the first time. However, even after I hide the tab bar, or move its frame out of the screen, the UIView still crops itself as if the tab bar was still there.
Both of these code blocks produced the same result:
[appDelegate.tabBarController.tabBar setFrame:CGRectMake(0,1000,0,0)];
[self setView:InitialView];
and
[appDelegate.tabBarController.tabBar setHidden:YES];
[self setView:InitialView];
Here's a screenshot of the incident in action:
Does anyone know how to fix this problem? I've been puzzling away at this for the past few hours, and I can't seem to do anything about it.
Presumably you have your view's view controller inside this tab bar controller. As a result, the view controller's view is getting sized appropriately to fit inside the tab bar controller's view. Why don't you just get the frame of the tab bar and adjust the height of your view by the view's current height + the tab bar's height?
As a side note, I am assuming InitialView is a UIView (or subclass) instance. It is standard Object-Oriented Programming convention to name instances of classes with a lower case letter, and then to proceed in camel case, as in initialView. Just an FYI.
Try this reference your App Delegate which should take in account the UITabBarController. Just the UIImageView as a subview, and when you are done just remove it. You'll obviously have to import your AppDelegate.
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
[imageView addSubview:appDelegate.window];
in an iPad application, I am displaying a modal view controller (through presentModalViewController) in a FormSheet style (so it's about 540 pixels wide and high), the root view controller displays fine (its frame's size is set to roughly (540, 540) and my code takes care of laying out the content properly).
However, when a push a view controller, its frame's size always has (768, 1024) which is wrong. I tried to set its frame explicitly like this:
DetailViewController* detailController = [[DetailViewController alloc] init];
detailController.view.frame = self.view.frame;
[self.navigationController pushViewController:detailController animated:YES];
Any ideas why it doesn't set the size properly?
well, layoutSubviews should be used if the actual frame of the view at runtime is needed. I ended up using that to lay the subviews inside the controller's view. (although I had to create a custom UIView subclass for controller's view)
Your approach looks right. Forgive my question, but have you debugged this with breakpoints and GDB?
You might try this from the console (cmd shift r):
print [[self view] frame]
and
print [[detailController view] frame]
print this before and after you call pushViewController:animated on the UINavigationController to see if its frame size changes from the pushViewController:animated method.
Another note, its hard to see a use case for pushing a view controller to a UINavigationController that would NOT consume the entire UINavigationController's views area. Every push onto the navigation controller represents a level deeper into some navigation (unlike UIView - addSubView).
http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
Update: This is why you are having problems:
The view is automatically resized to fit between the navigation bar and toolbar (if present) before it is displayed.
You will find that on apple's documentation on the link I provided. See pushViewController:animated:
View controllers are expected to manage an entire "screenful" of content. Only one view controller (not counting container controllers like UINavigationController) is active at any given moment. The only exception is UISplitViewController, which allows two view controllers to have content on the screen at once.
I have an application with a navigation bar and a tab bar. A user can navigate to a view which displays images in a scroll view. I'd like to have the same behavior as the iPhone photo app: Nav bar at the top, tool bar at the bottom, which will hide or show based upon a tap.
I'm moving my view to the window object in order to achieve full screen mode. This works fine:
myView = [self.view retain];
self.view = nil;
[window addSubview:myView];
But when I want to redisplay the Nav & tool bar, I run into a problem. The bars show fine, but the view is empty, and I can't seem to add any content to the view:
[myView removeFromSuperview];
self.view = myView;
I got a lot of good info from this post
but can't quite get the right combination.
By simply setting the controller's view, you aren't adding it as a subview to anything else, so it will never appear.
Moving views around like this can get a little tricky. I recommend that you not move the view from one to the other, but instead have two UIViews. Add second UIView to the window's subview and set it to hidden=YES initially. When you want to show it, set the image for the UIImageView, and then set the hidden property to NO.
what's wrong with just using setNavigationBarHidden: animated: and setToolbarHidden:animated:?
I've been working pretty extensively the last couple months with UIImagePickerController, particularly with the new capabilities in OS3.1 and newer to overlay views on-top of the camera view. This has worked just fine.
However, I am currently working on a project where I'd like to be able to display the camera view of the UIImagePickerController within an existing view. Essentially, the exact opposite of what I've currently been doing.
An example would be a View Controller with navigation components (Think top and bottom horizontal bars with gradients), and upon tapping a button on one of these bars, then content area displays the camera view. The shutter animation would should up, and the top and bottom navigation bars would remain always on-top.
I've had success adding the UIImagePickerController to the window view, as well as presenting it modally, but haven't had any luck adding it as a subView.
ex:
[window addSubview:camera.view];
[self presentModalViewController:camera animated:YES];
All you need to do is call viewWillAppear and viewDidAppear.
Here is an example where _pickerController is an instance of UIImagePickerController:
[self.view addSubview:_pickerController.view];
[_pickerController viewWillAppear:YES];
[_pickerController viewDidAppear:YES];
Call viewWillAppear:YES on the image picker controller after adding its view to your view. Skip the modal view controller business.
I don't think the API provides direct access to the actual view of the UIImagePickerController. The class is actually a subclass of UINavigationController so I don't think it has an actual view itself but rather manages the calling of its subcontrollers and their views.
When you call the UIImagePickerController modally, its doesn't add the views it controls as subviews to the window (or any other view). That is what a modal view means. It presents the view off to the "side" of the view hierarchy.
Even if you could hack this together, I think Apple would reject it as not being part of the API and for violating the HIG.