How come a UIViewController's view coordinate system starts after the navbar, but its height includes the navbar? - ios

I noticed that with a NavigationController on an iPhone, the height is 460. So it includes the whole screen except the status bar.
However, when I add something at coordinate 0, it shows up after the NavigationBar, although the size of the navigation bar is included in the height (meaning the entire frame of this view sticks off the screen).
Did I make a mistake? If not, why is it structured this way?
NSLog(#"Frame: %#", [NSValue valueWithCGRect: self.view.frame]); // prints {(0, 20), (320, 460)}
UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame: CGRectMake(0, self.navigationController.navigationBar.frame.size.height, self.view.frame.width, 50)];
[self.view addSubview: scrollView]; // showing up 44px *after* the nav bar

I already answered your other similar question, but here is one for this.
In viewDidLoad you will see the views height as 460 because at that point it hasn't resized to account for the Nav Bar.
But If you printed the same frame out in say viewWillAppear you will see that now the frames height has adjusted for the Nav Bar.
So if you want to add something in viewDidLoad, you need to add it based on the views frame, add whichever resizing mask will do the job you want, and see it adjust correctly once the view appears.

Related

UIScrollview position moves after touches begin

I view imbedded in a Navigation Controller which is slightly transparent. This view contains a UIscrollview. This UIScrollview has the following subviews: UIImageView, UILabel, and UIWebview. All these other views are working correctly. When the view loads, everything is in the correct position (The views are below the Navigation Bar). However, as soon as the screen is tapped, the scrollview repositions itself to the top of the view (aka behind the Navigation Bar, which is at the top, and I can see that this is true because the Nav Bar is slightly transparent)
Any idea why this is happening? I set up the scrollview like this:
self.scrollView.frame = CGRectMake(0, self.navigationController.navigationBar.frame.size.height, self.view.window.frame.size.width, self.view.window.frame.size.height);
Also set these properties:
self.scrollView.scrollEnabled = YES;
self.scrollView.alwaysBounceVertical = YES;
self.scrollView.bounces = YES;
Anybody know why this is happening?
I'd similar problem, but only on iOS 7.0. Try to set the translucent = NO property of the navigationBar. This will make the navigationBar opaque. Although if you want the navigationBar to be transparent, try to change the contentInset of the scrollView to adjust the content as you want. Hope that this will help :)

iOS: Changing the height of the main view

How would you change the height of the main view so that its height does not go beyond the tabbed navigation bar? I want the main view to be above the tabbed navigation bar.
I believe you want the content to not show up behind the navigation bar. If this is correct you can uncheck the Under Top Bars in your view controller.
You can try this with code
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
you may also need to add
self.navigationController.navigationBar.translucent = NO;
The self.navigationController.navigationBar.translucent = NO; should be all you need, however depending on your setup and what you are doing with the navigation bar you may need the additional code above.
You can add those into your viewDidLoad or into viewDidLayoutSubviews
If that doesn't work you can try something like this if you need to support ios 6 as well.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.view.frame = CGRectMake(0,
self.topOfViewOffset,
self.view.frame.size.width,
self.view.frame.size.height);
}
So if you have a content view that has a width as wide as your ViewController, that has an origin point of 0,0 (it's top left corner starts at the very top left hand corner of the view) and that has a navigation controller directly below it, I would do something like this in my ViewDidLoad method:
yourcontentview.frame = CGRectMake(0, //x co-ordinate
0, //y co-ordinate
self.view.frame.width, //set width as wide as the view's
self.view.frame.height - yournavigationbar.frame.height); //take the height of the nav controller away from the view and see what space is left.
or alternatively if your nav controller is NOT at the very bottom of your view change:
self.view.frame.height - yournavigationbar.frame.heigh
to
self.view.frame.heigh - yournavigationbar.frame.origin.y
The above ^ gets the start location of the nav controller in the view (so if it starts at 500 points down, then the height of the contentview will not go past 500 points)
Hope they work!
also if there is lots of content, you can always stick it in a scrollview :)

Finding The Center of a View

I have an iphone app with 2 ViewControllers . Both screens(viewcontrollers) show a loading screen. I create the loading screen programmatically:
UIView *loadingScreen = [[UIView alloc] initWithFrame:CGRectMake(100,200,144,144)];
loadingScreen.center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0);
//{.. Other customizations to loading screen
// ..}
[self.view addSubview:loadingScreen];
For some reason, the second viewcontroller's loadingScreen is significantly lower and it isn't centered on the screen. The first viewcontroller works perfectly and is dead center like I want.
The second viewcontroller is a UITableView and it shows the uinavigationbar, whereas the first viewcontroller doesn't show the uinavigationbar. Also, I use storyboard for my app.
I've outputted to the NSLog self.view.frame.size.height and loadingScreen.center in both instances and THEY HAVE THE SAME COORDINATES! So, not sure why it is showing up lower. Any ideas why the second loadingScreen is lower and how to fix? Thanks!
You mention that one screen displays a UINavigationBar while the other does not. When you display a navigation bar, it offsets the rest of your view - in this case by shifting it down.
There are two quick fixes. You can either adjust your center point up by the size of the UINavigationBar (65 pts - unless it's a custom UINavigationBar and you've changed its size) or you can set the "Adjust Scroll View Insets" value to false in the attributes inspector.
The latter is probably the easiest and comes most recommended. Note though, that the top of your UITableView will now be underneath the UINavigationBar.
My final note would be that if you wanted to do it programmatically than in your UITableView's delegate you can call
- (BOOL)automaticallyAdjustsScrollViewInsets
{
return NO;
}

Screen bounds extends visible area

I'm trying to make a square (50 x 50) UIView in the lower right hand of my main view, but I'm confused about why it's not entirely visible. In this instance, only the tip of it is visible from the bottom. Am I confusing some concept?
CGFloat width = CGRectGetWidth(self.view.bounds);
CGFloat height = CGRectGetHeight(self.view.bounds);
UIView *transparentFloater = [[UIView alloc] initWithFrame:CGRectMake(width - 50.f, height - 50.0f, 50.0f, 50.0f)];
[self.view addSubview:transparentFloater];
Try to add the autoresizing mask:
transparentFloater.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin;
If I am not wrong, You have created your ViewController with xib and in the attributes of view, you have forgot to mention that you are using a "navigation bar" as "top bar".
Reason
So in ViewDidLoad, view in .xib with a height X is returned. But as you might have loaded the viewController using UINavigationController, after loading the height of view is decreased by 44pixels.
Suggestions :
1) Whenever you know that you are going to have navigation bar on top please mention it in .xib file as well.
For doing so click on the view in xib and select the option called topbar in attributes Inspector of utilities area
2) Call the following api
NSLog(#"In ViewDidAppear %#",NSStringFromCGRect(self.view.bounds));
in
viewDidLoad
viewDidAppear
to track whats happening with the bounds of view
You does not need to do anything just put
transparentFloater.backgroundColor = [UIColor redColor];
because your view (custom) is invisible (because your main view color and custom view color are same (white) ) may be. I tried your code in my demo project. it worked perfectly for me.

Frame sizing of tableview within nested child controllers/subviews

I'm a bit confused by the proper frame sizing of a table view to fit within my screen.
Here's my setup of view controllers within view controllers:
UITabBarController
UINavigationController as one of the tab bar viewcontrollers; title bar hidden
ViewController - a container view controller because I need the option to place some controls beneath the UITableView, sometimes (but not in the current scenario)
UITableViewController
Now, my question is what the proper frame dimensions of the UITableview should be. Here's what I've got in the ViewController viewDidLoad method. I used subtracted 49.0 (the size of the tab bar) from 480.0. However, this leaves a black bar at the bottom. 20.0 appears to do it (coincidentally?) the size of the status bar, but I don't understand why that would be. Wouldn't the true pixel dimensions of the tableview be 480-49?
// MessageTableViewController is my subclass of UITableViewController
MessagesTableViewController *vcMessagesTable = [[MessagesTableViewController alloc] init];
CGRect tableViewFrame = CGRectMake(0, 0, 320.0, 480.0 - 49.0);
[[vcMessagesTable view] setFrame:tableViewFrame];
self.tableViewController = vcMessagesTable;
[self addChildViewController:vcMessagesTable];
[[self view] addSubview:vcMessagesTable.view];
Here's how it looks:
I've run into this problem also -- I think it would be best not to hard code the size but to refer to the size of one its ancestor controllers. In this case, the UINavigationController, that's the direct child of the tabBar controller should have the right frame to fill the whole screen minus the tabBar. So I would subtract (if you need to) from that frame height if you want space at the bottom, otherwise, just use that frame. I think that self.navigationController finds the nearest nav controller above your controller of interest.

Resources