Why the 20px gap at the top of my UIViewController?
The Problem
Consider the following controller hierarchy:
UINavigationController
UIViewController
UITableViewController
The presence of the UIViewController
is affecting layout. Without it, the UITableViewController
takes up the entire bounds of the UINavigationController
:
However, if I add a vanilla UIViewController
between the UINavigationController
and UITableViewController
, a 20px gap appears between the top of the UIViewController
and the top of the UITableViewController
:
Even if I reduce my code down to the simplest possible thing, I still observe this behavior. Consider this app delegate code:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
window = new UIWindow(UIScreen.MainScreen.Bounds);
var tableView = new UITableViewController();
var intermediateView = new UIViewController();
var navigation = new UINavigationController(intermediateView);
navigation.View.BackgroundColor = UIColor.Red;
intermediateView.View.BackgroundColor = UIColor.Green;
tableView.View.BackgroundColor = UIColor.Blue;
intermediateView.AddChildViewController(tableView);
intermediateView.View.AddSubview(tableView.View);
tableView.DidMoveToParentViewController(intermediateView);
window.RootViewController = navigation;
window.MakeKeyAndVisible();
return true;
}
The above still shows a 20px gap between the top of the UIView
and the top of the UITableView
.
My Understanding of the Problem
I understand that something is erroneously allocating space for a status bar. Using Reveal I can see that the Frame
of the UITableViewController
has a Y
value of 20
.
Things I've Tried
Unsuccessful
- Set
WantsFullScreenLayout
totrue
on theUIViewController
,UITableViewController
, and both - Playing with
EdgesForExtendedLayout
andExtendedLayoutIncludesOpaqueBars
for both theUIViewController
andUITableViewController
- Played with
AutomaticallyAdjustsScrollViewInsets
on theUIViewController
- Played with
PreservesSuperviewLayoutMargins
in theUITableView
- Tried overriding
PrefersStatusBarHidden
and returningtrue
in both theUIViewController
andUITableViewController
Successful
Overriding ViewDidLayoutSubviews
in my UITableViewController
thusly:
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
this.View.Frame = this.View.Superview.Bounds;
}
Things I want to know
- is there a clean(er) way of achieving my goal?
- what is actually responsible for adding the 20px gap? The
UIViewController
? TheUITableViewController
? - what are the best practices for ensuring my view controllers remain usable in different contexts? Presumably overriding
ViewDidLayoutSubviews
couples my view controller to expectations as to where it will be displayed in the visual tree. If it were to be hosted higher up the controller stack, things would not look right. Is there a way to avoid this coupling and thus increase reusability?