Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does UIViewController extend under UINavigationBar, while UITableViewController doesn't?

I have UITabbarController with UINavigationController in it. I have a subclass of UIView that I assign as the view of UIViewController in the navController. This is pretty standard stuff, right? This is how I do it

_productCategoryView = [[ProductCategoryView alloc] initWithFrame:self.view.frame]; self.view = _productCategoryView; 

This view has a UITableView as subView

_productCategoryTableView = [[UITableView alloc] initWithFrame:self.frame style:UITableViewStylePlain]; _productCategoryTableView.separatorStyle = UITableViewCellSeparatorStyleNone; _productCategoryTableView.backgroundColor = [UIColor clearColor]; [self addSubview:_productCategoryTableView]; 

For the sake of debugging I am setting self.backgroundColor = [UIColor blueColor] on the view.

From the above initialization of tableView one might think that the view's and table's frame is same. However when I run in iOS 7, the view's origin is set behind the UINavigationBar. This is understandable because I am setting self.navigationBar.translucent = YES; in my subclass of UINavigationController. But what I don't understand is how come the table is sitting just below the navBar? Shouldn't it also start from (0, 0) which is behind the navBar? See screenshot Scenario 1 below. Notice the blue hue behind navBar

Scenario 1

Now, I push another viewController on the navigation stack, simply by using [self.navigationController pushViewController.....]. Again I have a custom UIView with a tableView in it. However I also have a UILabel above this table, and again for debugging, I gave it a redColor. This time I am setting the label's origin to be almost same as the view's

CGRect boundsInset = UIEdgeInsetsInsetRect(self.bounds, UIEdgeInsetsMake(10, 10, 10, 10));  CGSize textSize = [_titleLabel.text sizeWithFont:_titleLabel.font                                constrainedToSize:CGSizeMake(boundsInset.size.width, MAXFLOAT)                                    lineBreakMode:NSLineBreakByWordWrapping]; printSize(textSize); _titleLabel.frame = CGRectMake(boundsInset.origin.x,                                boundsInset.origin.y,                                boundsInset.size.width,                                textSize.height); 

So, going by the logic above, the label should be visible, right? But this time it's not. This time the label is behind the navBar.

Scenario - 2

Notice, the red hue behind navBar.

I would really like to align the subView below the navBar consistently. My questions are

1. How is the tableView offset by 64pixels (height of nav + status bar in iOS 7) automatically, even though it's frame is same as the view's?

2. Why does that not happen in the second view?

like image 257
unspokenblabber Avatar asked Oct 02 '13 17:10

unspokenblabber


2 Answers

By default, UITableViewController's views are automatically inset in iOS7 so that they don't start below the navigation bar/status bar. This is controller by the "Adjust scroll view insets" setting on the Attributes Inspector tab of the UITableViewController in Interface Builder, or by the setAutomaticallyAdjustsScrollViewInsets: method of UIViewController.

For a UIViewController's contents, if you don't want its view's contents to extend under the top/bottom bars, you can use the Extend Edges Under Top Bars/Under Bottom Bars settings in Interface Builder. This is accessible via the edgesForExtendedLayout property.

like image 59
Greg Avatar answered Sep 22 '22 17:09

Greg


Objective-C:

- (void)viewDidLoad {     [super viewDidLoad];     self.edgesForExtendedLayout = UIRectEdgeNone;  } 

Swift 2:

self.edgesForExtendedLayout = UIRectEdge.None 

Swift 3+:

self.edgesForExtendedLayout = [] 
like image 29
Gank Avatar answered Sep 20 '22 17:09

Gank