为啥 UIViewController 在 UINavigationBar 下扩展,而 UITableViewController 没有?

Posted

技术标签:

【中文标题】为啥 UIViewController 在 UINavigationBar 下扩展,而 UITableViewController 没有?【英文标题】:Why does UIViewController extend under UINavigationBar, while UITableViewController doesn't?为什么 UIViewController 在 UINavigationBar 下扩展,而 UITableViewController 没有? 【发布时间】:2013-10-09 05:11:48 【问题描述】:

我有UITabbarControllerUINavigationController。我有一个UIView 的子类,我在navController 中指定为UIViewControllerview。这是很标准的东西,对吧?我就是这样做的

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

这个view 有一个UITableView 作为subView

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

为了调试,我在视图上设置了self.backgroundColor = [UIColor blueColor]

从上面tableView 的初始化可能会认为视图和表的frame 是相同的。但是,当我在ios 7 中运行时,视图的原点设置在UINavigationBar 后面。这是可以理解的,因为我在UINavigationController 的子类中设置了self.navigationBar.translucent = YES;。但我不明白的是,这张桌子怎么就坐在navBar 的正下方?它不应该也从(0, 0) 后面的navBar 开始吗?请参阅下面的屏幕截图Scenario 1。注意navBar后面的蓝色调

现在,我在导航堆栈上push 另一个viewController,只需使用[self.navigationController pushViewController.....]。同样,我有一个自定义的UIView,里面有一个tableView。但是我在这个表上方也有一个UILabel,为了调试,我给了它一个redColor。这次我将标签的origin 设置为与视图的几乎相同

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);

所以,按照上面的逻辑,标签应该是可见的,对吧?但这次不是。这次标签在navBar 后面。

注意,navBar 后面的红色调。

我真的很想始终对齐导航栏下方的子视图。我的问题是

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?

【问题讨论】:

您是否使用 Xcode 5 和 iOS7 SDK 进行构建? 【参考方案1】:

默认情况下,iOS7 中 UITableViewController 的视图会自动插入,因此它们不会从导航栏/状态栏下方开始。这是通过 Interface Builder 中 UITableViewController 的 Attributes Inspector 选项卡上的“调整滚动视图插入”设置或 UIViewController 的 setAutomaticallyAdjustsScrollViewInsets: 方法设置的控制器。

对于 UIViewController 的内容,如果您不希望其视图的内容在顶部/底部栏下扩展,您可以使用 Interface Builder 中的 Extend Edges Under Top Bars/Under Bottom Bars 设置。这可以通过edgesForExtendedLayout 属性访问。

【讨论】:

谢谢@Greg。设置self.edgesForExtendedLayout = UIRectEdgeNone; 成功了。 谢谢。解决 edgeForExtendedLayout 完成为我解决了 uitableview-as-a-a-subview-of-navcontroller 布局问题;在过去的 8 个月里,在这方面花费了无数小时。 在使用 navigationController 进行推送转换时,我注意到导航栏应用了“延迟”颜色处理。是什么原因造成的,如何消除? 在上面的评论中使用@unspokenblabber 的sn-p,这也可以防止您不得不为视图控制器XIB 手动设置64px 的上边距。 @IphoneDeveloper,试试:self.navigationController.navigationBar.translucent = NO;【参考方案2】:

目标-C:

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

斯威夫特 2:

self.edgesForExtendedLayout = UIRectEdge.None

斯威夫特 3+:

self.edgesForExtendedLayout = []

【讨论】:

设置self.edgesForExtendedLayout = [] 改变UINavigationBar 颜色。【参考方案3】:

@Gank 的回答是正确的,但最好的地方是UINavigationControllerDelegate(如果你有的话):

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) 
    viewController.edgesForExtendedLayout = UIRectEdge.None

【讨论】:

@Jaybo 谢谢,是的,你把代码放在哪里有很大的影响。

以上是关于为啥 UIViewController 在 UINavigationBar 下扩展,而 UITableViewController 没有?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UIViewController 在 UINavigationBar 下扩展,而 UITableViewController 没有?

为啥 UIViewController 是 UIResponder 的子类?

模态 UIViewController 总是在 iPad 上全屏显示。为啥?

为啥我不能在 Swift 中调用 UIViewController 上的默认 super.init()?

为啥我们将 UIViewController 传递给 UINavigationController 类?

为啥情节提要 ui 元素未显示在 xcode 9 中的 UIViewController 上