考虑以下控制器层次结构:
UINavigationController
UIViewController
UITableViewController
UIViewController
的存在正在影响布局。没有它,UITableViewController
会占用UINavigationController
:
但是,如果我在UIViewController
和UINavigationController
之间添加一个香草UITableViewController
,则UIViewController
的顶部和{{的顶部之间会出现20px的差距1}}:
即使我将代码减少到最简单的东西,我仍然会观察到这种行为。考虑一下这个app代理代码:
UITableViewController
以上仍显示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
的顶部之间存在20px的差距。
我知道某些东西错误地为状态栏分配空间。使用显示我可以看到UITableView
的{{1}}的{{1}}值为Frame
。
UITableViewController
,Y
和20
设为WantsFullScreenLayout
true
和UIViewController
UITableViewController
和EdgesForExtendedLayout
ExtendedLayoutIncludesOpaqueBars
UIViewController
进行了游戏
UITableViewController
AutomaticallyAdjustsScrollViewInsets
玩
UIViewController
和PreservesSuperviewLayoutMargins
UITableView
并返回PrefersStatusBarHidden
在我的true
覆盖UIViewController
:
UITableViewController
ViewDidLayoutSubviews
? UITableViewController
?public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
this.View.Frame = this.View.Superview.Bounds;
}
将我的视图控制器与可视化树中显示的位置联系起来。如果将它托管在控制器堆栈的更高位置,事情看起来就不对了。有没有办法避免这种耦合,从而提高可重用性?答案 0 :(得分:36)
您所看到的行为根本不是一个错误,而只是您滥用将视图添加到层次结构中的副作用。
当您将tableView添加到视图中时,您需要告诉UIKit您希望tableView相对于其父级的大小。您有两种选择:Auto-Layout或Autoresizing Masks。如果没有描述您希望视图布局UIKit
的方式,只需将其弹出到层次结构中,默认实现就会将您的视图放在顶部布局指南下(恰好是状态栏的高度)。像这样简单的东西可以解决问题:
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实现会在状态栏下隐藏视图。如果我们使childController成为一个简单的UIViewController
子类,则不会出现这种行为。不要认为这是一个bug,如果你明确声明你希望如何布置他们各自的观点,你就不会有这个问题。当然,这是容器控制器的主要功能。
你的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;
}
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,描述了配置视图以填充其超级视图的方法
答案 1 :(得分:8)
您的问题似乎与某些基本问题有关,UITableViewController
被直接添加为另一个的子控制器。
展望这不是一个新问题:iOS 7: UITableView shows under status bar
相对于那篇文章,我拿了你的代码并尝试了以下选项(一旦我意识到它是在C#8 ^)):
不是使用UITableViewController
,而是添加UIViewController
然后添加UITableView
作为UIViewController
的子级。
如果你这样做,那么就没有20pt的问题。这突出了
问题在于UITableViewController
类。
这种方法是一种相对干净的解决方法,只有几种 你已经拥有的额外步骤。
我确实尝试在原始代码中添加约束来强制执行 UITableViewController框架到顶部,但无法得到这个 工作。这又可以归结为表控制器的覆盖 事物本身。
如果您使用故事板构建演示,一切正常。这个我
相信是因为IB本身使用容器视图
嵌入新的视图控制器。所以,如果你使用故事板,那么
apple是否添加了一个可以设置使用框架的视图
约束然后将UITableViewController
嵌入其中
通过嵌入Segue的观点。
因此,根据1),使用中间的视图似乎解决了这个问题
似乎可以控制中间视图frame
是关键。
我注意到你唯一可行的解决方法是改变框架 答案。但是在iOS7之后,似乎没有改变框架 由于可能与之发生冲突的问题而被推荐 也想要操纵框架的约束。
edgesForExtendedLayout
失败。这些似乎是容器视图控制器和提示的提示
UITableViewController忽略了它们。恕我直言,我认为选项1)似乎是最安全的方法,因为您可以完全控制布局,并且不会使用帧覆盖来对抗系统,这可能会导致您稍后出现问题。选项2)只有在使用故事板时才能真正起作用。您可以尝试自己手动执行相同的操作,但是谁知道在嵌入Segue中发生了什么。
修改强>
似乎Arkadiusz Holko在他的回答中强调了一个缺失的步骤,并且明确地为表视图设置框架确实解决了问题。
答案 2 :(得分:6)
添加子视图控制器时,您错过了一步 - 设置视图的框架。
见第二步:
- (void) displayContentController: (UIViewController*) content;
{
[self addChildViewController:content]; // 1
content.view.frame = [self frameForContentController]; // 2
[self.view addSubview:self.currentClientView];
[content didMoveToParentViewController:self]; // 3
}
答案 3 :(得分:4)
状态栏占用20个像素。如果您使用具有自动布局的xib文件或故事板,则可以将顶部约束设置为顶部布局指南,以便处理20像素差异
答案 4 :(得分:2)
是否有实现目标的干净方式?
只需更改框架。
Error in clusplot.default ( x$data , x$clustering, diss = FALSE, main = main :
argument 5 corresponds to several formal arguments
实际负责添加20px差距的原因是什么? UIViewController? UITableViewController?
您可以在新tableView.View.Frame = intermediateView.View.Bounds;
tableView.View.AutoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
后记录UIViewController.view.frame
。
您可以看到UIViewController
总是有20px的差距。为什么?我认为Apple只是使用20px的顶部填充来初始化UITableViewController.view.frame
屏幕大小。
确保我的视图控制器在不同环境中保持可用的最佳做法是什么? ... 强>
如果您想将UITableViewController.view
添加到另一个UIViewController.view
。最好的方法是使用故事板并使用UIViewController.view
。
如果您不想或不能使用故事板。我建议只是子类Container View
。 UIView
有时会对生活圈和布局产生恼人的问题。