问题
考虑以下 Controller 层次结构:
UINavigationController
UIViewController
UITableViewController
UIViewController
的存在会影响布局。没有它,UITableViewController
会占据 UINavigationController
的整个边界:
但是,如果我在 UINavigationController
和 UITableViewController
之间添加一个 Vanilla UIViewController
, 顶部之间会出现 20px 的间隙UIViewController
和 UITableViewController
的顶部:
即使我将我的代码减少到最简单的可能,我仍然观察到这种行为。考虑这个应用委托(delegate)代码:
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;
}
上面的仍然显示了 UIView
顶部和 UITableView
顶部之间有 20px 的间隙。
我对问题的理解
我知道某事错误地为状态栏分配了空间。使用 Reveal,我可以看到 UITableViewController
的 Frame
的 Y
值为 20
。
我尝试过的事情
不成功
- 在
UIViewController
、UITableViewController
和两者上将WantsFullScreenLayout
设置为true
- 为
UIViewController
和UITableViewController
使用EdgesForExtendedLayout
和ExtendedLayoutIncludesOpaqueBars
- 在
UIViewController
上玩过AutomaticallyAdjustsScrollViewInsets
- 在
UITableView
中使用PreservesSuperviewLayoutMargins
- 尝试覆盖
PrefersStatusBarHidden
并在UIViewController
和UITableViewController
中返回true
成功
因此在我的 UITableViewController
中覆盖 ViewDidLayoutSubviews
:
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
this.View.Frame = this.View.Superview.Bounds;
}
我想知道的事
- 是否有一种干净(呃)的方式来实现我的目标?
- 增加 20px 间隙的真正原因是什么?
UIViewController
?UITableViewController
? - 确保我的 View Controller 在不同上下文中保持可用的最佳做法是什么?大概覆盖
ViewDidLayoutSubviews
将我的 View Controller 与关于它将在可视化树中显示的位置的期望相结合。如果它被托管在 Controller 堆栈的更高位置,事情看起来就不对了。有没有办法避免这种耦合,从而提高可重用性?
最佳答案
您看到的行为根本不是错误,而仅仅是您滥用将 View 添加到层次结构的副作用。
当您将 tableView 添加到 View 中时,您需要告诉 UIKit 您希望 tableView 相对于其父 View 的大小如何。您有两个选择:Auto-Layout或自动调整蒙版。无需描述您希望 View 如何布局,UIKit
只是将其弹出到层次结构中,默认实现会将您的 View 置于顶部布局指南下方(恰好是状态栏的高度)。像这样简单的事情就可以解决问题:
tableVC.View.Frame = rootVC.View.Bounds
tableVC.View.Autoresizingmask = UIViewAutoresizing.FlexibleWidth
tableVC.View.TranslatesAutoresizingMaskIntoConstraints = true// always nice to explicitly use auto layout
此行为实际上并非 UITableViewController
独有,UICollectionViewController
也独有。我相信他们的默认 viewLoading 实现会在状态栏下插入 View 。如果我们使我们的 childController 成为一个简单的 UIViewController
子类,则不会出现任何这种行为。不要将此视为错误,如果您明确声明您希望如何布置它们各自的 View ,则不会出现此问题。自然,这是容器 Controller 的主要功能。
你的 appDelegate 应该是这样的:
赛马林
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
window = new UIWindow(UIScreen.MainScreen.Bounds);
var tableVC = new UITableViewController();
var rootVC = new UIViewController();
var navigationVC = new UINavigationController(intermediateView);
navigationVC.View.BackgroundColor = UIColor.Red;
rootVC.View.BackgroundColor = UIColor.Green;
tableVC.View.BackgroundColor = UIColor.Blue;
rootVC.AddChildViewController(tableVC);
rootVC.View.AddSubview(tableVC.View);
//YOU NEED TO CONFIGURE THE VIEWS FRAME
//If you comment this out you will see the green view under the status bar
tableVC.View.Frame = rootVC.View.Bounds
tableVC.View.Autoresizingmask = UIViewAutoresizing.FlexibleWidth
tableVC.View.TranslatesAutoresizingMaskIntoConstraints = true
tableVC.DidMoveToParentViewController(rootVC);
window.RootViewController = navigationVC;
window.MakeKeyAndVisible();
return true;
}
swift
var window: UIWindow?
var navigationControlller: UINavigationController!
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let rootVC = UIViewController(nibName: nil, bundle: nil)
let tableVC = UITableViewController(style: .Plain)
let navVC = UINavigationController(rootViewController: rootVC)
navVC.navigationBarHidden = true
navVC.view.backgroundColor = UIColor.redColor()
rootVC.view.backgroundColor = UIColor.greenColor()
rootVC.view.addSubview(tableVC.view)
//YOU NEED TO CONFIGURE THE VIEWS FRAME
//If you comment this out you will see the green view under the status bar
tableVC.view.frame = rootVC.view.bounds
tableVC.view.autoresizingMask = .FlexibleWidth | .FlexibleHeight
tableVC.view.setTranslatesAutoresizingMaskIntoConstraints(true)
rootVC.addChildViewController(tableVC)
tableVC.didMoveToParentViewController(rootVC)
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = navVC
window?.makeKeyAndVisible()
return true
}
注意 我写了一个post recently描述配置 View 以填充其父 View 的方式
关于ios - 为什么我的 UIViewController 顶部有 20px 的间隙?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30525403/