为啥 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 【问题描述】:我有UITabbarController
和UINavigationController
。我有一个UIView
的子类,我在navController
中指定为UIViewController
的view
。这是很标准的东西,对吧?我就是这样做的
_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()?