iOS 7:UITableView显示在状态栏下
我的应用程序的第一个屏幕是一个没有导航栏的iOS 7:UITableView显示在状态栏下,ios,ios7,uistatusbar,Ios,Ios7,Uistatusbar,我的应用程序的第一个屏幕是一个没有导航栏的UITableViewController,这意味着内容在状态栏下流动,因此存在大量文本冲突。我已经调整了顶部栏下的属性和调整滚动视图插入项,这实际上阻止了它在下面滚动,但代价是将表视图的顶部保持在下面。我已尝试将UITableView帧设置为偏移20像素,但它似乎没有生效,而且由于我当前需要应用程序与iOS 6兼容,我无法跳转到iOS 7故事板以强制自动布局使用顶部高度指南。是否有人找到了一个同时适用于两个版本的解决方案 我尝试过的方法:设置edges
UITableViewController
,这意味着内容在状态栏下流动,因此存在大量文本冲突。我已经调整了顶部栏下的属性和调整滚动视图插入项
,这实际上阻止了它在下面滚动,但代价是将表视图的顶部保持在下面。我已尝试将UITableView
帧设置为偏移20像素,但它似乎没有生效,而且由于我当前需要应用程序与iOS 6兼容,我无法跳转到iOS 7故事板以强制自动布局使用顶部高度指南。是否有人找到了一个同时适用于两个版本的解决方案
我尝试过的方法:设置edgesForExtendedLayout
,在故事板中更改顶部栏下的设置,以及调整滚动视图
,强制帧到新区域
一幅画胜过千言万语:
如果您还需要支持iOS 6,则必须有条件地将其下移。也就是说,在iOS 7中,您只需将其向下移动20个点(通过frame
操作或使用自动布局),而在iOS 6中,您可以不使用它。我不相信你能在IB中做到这一点,所以你必须在代码中做到
编辑
实际上,您可以在IB中通过使用iOS6/iOS7增量来实现这一点。在iOS 7中设置您的位置,然后在iOS 6中将增量Y设置为-20点。有关更多信息,请参阅。我认为使用UITableViewController的方法可能与您以前所做的略有不同。这对我很有用,但你可能不是它的粉丝。我所做的是有一个视图控制器,它带有指向我的UItableViewController的容器视图。通过这种方式,我可以在故事板中使用提供给我的TopLayoutGuide。只需将约束添加到容器视图中,您就可以同时使用iOS7和iOS6了。对于任何有兴趣复制此约束的人,只需执行以下步骤:
创建一个新的iOS项目
打开主情节提要并删除默认/初始UIViewController
从对象库中拖出一个新的UITableViewController
将其设置为初始视图控制器
向表格提供一些测试数据
如果您按照上述步骤操作,当您运行应用程序时,您将看到没有任何东西可以阻止第一行出现在状态栏下,包括调整Xcode的复选框以“在{Top,Bottom,不透明}条下延伸边”,您也无法通过编程解决此问题
例如,在上述情况下,以下情况不会产生任何影响:
// These do not work
self.edgesForExtendedLayout=UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars=NO;
self.automaticallyAdjustsScrollViewInsets=NO;
这个问题可能非常令人沮丧,我认为这是苹果方面的一个缺陷,特别是因为它出现在他们自己的对象库中的预连线UITableViewController
中
我不同意任何人试图通过使用任何形式的“幻数”来解决这个问题,例如“使用20像素的增量”。这种紧密耦合的编程绝对不是苹果想要我们在这里做的
我发现了两种解决这个问题的方法:
- 保存
UITableViewController
的场景:
如果要将UITableViewController
保留在情节提要中,而无需手动将其放置在另一个视图中,则可以将UITableViewController
嵌入到UINavigationController
(编辑器>嵌入>导航控制器)中,并取消选中inspector中的“显示导航栏”。这解决了这个问题,不需要额外的调整,它还保留了故事板中的UITableViewController
场景
- 使用自动布局并将
UITableView
嵌入到另一个视图中(我相信这就是苹果希望我们这样做的方式):
创建一个空的UIViewController
,并在其中拖动UITableView
。然后,按住Ctrl键从UITableView
向状态栏拖动。当鼠标到达状态栏底部时,您将看到一个自动布局气泡,上面写着“顶部布局指南”。释放鼠标并选择“垂直间距”。这将告诉布局系统将其放置在状态栏的正下方
我在一个空的应用程序上测试了这两种方法,它们都可以工作。您可能需要进行一些额外的调整,以使它们适用于您的项目。请注意:这对我来说适用于以下配置:
- 屏幕顶部没有导航栏(表视图符合状态栏)
- 表视图是不可滚动的
如果上述两个要求不满足,您的差异可能会有所不同
原创帖子
我以编程方式创建了我的视图,这最终对我有效:
- (void) viewDidLayoutSubviews {
// only works for iOS 7+
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
CGRect viewBounds = self.view.bounds;
CGFloat topBarOffset = self.topLayoutGuide.length;
// snaps the view under the status bar (iOS 6 style)
viewBounds.origin.y = topBarOffset * -1;
// shrink the bounds of your view to compensate for the offset
viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
self.view.bounds = viewBounds;
}
}
(在第39页底部的“topLayoutGuide”部分中)。在故事板上选择UIViewController,取消选中顶部栏下的“延伸边缘”选项。
为我工作。
:)如果您以编程方式进行操作,并且使用的是UITableViewController
而没有UINavigationController
,那么您最好在viewDidLoad
中执行以下操作:
斯威夫特3
self.tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
早期斯威夫特
self.tableView.contentInset = UIEdgeInsetsMake(20.0f, 0.0f, 0.0f, 0.0f);
UITableViewController
仍将滚动到状态栏后面,但滚动到顶部时不会在状态栏下面
- (void) viewDidLayoutSubviews {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific
CGRect viewBounds = self.view.bounds;
CGFloat topBarOffset = self.topLayoutGuide.length;
viewBounds.origin.y = topBarOffset * -1;
self.view.bounds = viewBounds;
self.navigationController.navigationBar.translucent = NO;
}
}
我最后使用了一个具有所需背景的额外视图,添加在TableView之后,并放置在状态栏下:
self.CoverView = [[UIView alloc]init];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
self.CoverView.frame = CGRectMake(0,0,self.view.bounds.size.width,20);
}
self.CoverView.backgroundColor = [UIColor whiteColor];
self.TableView = [[UITableView alloc]initWithFrame:CGRectMake(0,
self.CoverView.bounds.size.height,XXX, YYY)];
[self.view addSubview:self.TableView];
[self.view addSubview:self.CoverView];
它不是很漂亮,但它是一个相当简单的解决方案,如果您需要使用无xib的视图,并且IOS6和IOS7都可以使用,我在UITableView的顶部有一个UISearchBar,下面的工作正常
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
self.tableView.contentOffset = CGPointMake(0, -20);
分享和享受…我已经为视网膜/非视网膜显示器做了这些
BOOL isRetina = FALSE;
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
if ([[UIScreen mainScreen] scale] == 2.0) {
isRetina = TRUE;
} else {
isRetina = FALSE;
}
}
if (isRetina) {
self.edgesForExtendedLayout=UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars=NO;
self.automaticallyAdjustsScrollViewInsets=NO;
}
我通过将大小设置为“自由形式”使其工作
我不知道它有多洁净,但我不知道
- (void)viewDidLoad {
[super viewDidLoad];
// Shove everything down if iOS 7 or later
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion >= 7.0f) {
// Move the view down 20 pixels
CGRect bounds = self.view.bounds;
bounds.origin.y -= 20.0;
[self.view setBounds:bounds];
// Create a solid color background for the status bar
CGRect statusFrame = CGRectMake(0.0, -20.0, bounds.size.width, 20);
UIView* statusBar = [[UIView alloc] initWithFrame:statusFrame];
statusBar.backgroundColor = [UIColor redColor];
[self.view addSubview:statusBar];
}
UIViewController *containerLeftViewController = [[UIViewController alloc] init];
UITableViewController *tableViewController = [[UITableViewController alloc] init];
containerLeftViewController.view.backgroundColor = [UIColor redColor];
hostsAndMoreTableViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
[containerLeftViewController.view addSubview:tableViewController.view];
[containerLeftViewController addChildViewController:tableViewController];
[tableViewController didMoveToParentViewController:containerLeftViewController];
NSDictionary * viewsDict = @{ @"tableView": tableViewController.view ,
@"topGuide": containerLeftViewController.topLayoutGuide,
@"bottomGuide": containerLeftViewController.bottomLayoutGuide,
};
[containerLeftViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|"
options:0
metrics:nil
views:viewsDict]];
[containerLeftViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide][tableView][bottomGuide]"
options:0
metrics:nil
views:viewsDict]];
tableView.contentInset = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion >= 7.0f) {
// Move the view down 20 pixels
CGRect bounds = self.view.bounds;
bounds.origin.y -= 20.0;
[self.navigationController.view setBounds:bounds];
// Create a solid color background for the status bar
CGRect statusFrame = CGRectMake(0.0, -20.0, bounds.size.width, 20);
UIView* statusBar = [[UIView alloc] initWithFrame:statusFrame];
statusBar.backgroundColor = [UIColor whiteColor];
[statusBar setAlpha:1.0f];
[statusBar setOpaque:YES];
[self.navigationController.view addSubview:statusBar];
}
- (void) viewDidLayoutSubviews {
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion >= 7.0f) {
CGRect bounds = self.view.bounds;
if(self.navigationController == nil || self.navigationController.isNavigationBarHidden == YES){
bounds.origin.y -= 20.0;
[self.view setBounds:bounds];
}
else{
self.edgesForExtendedLayout = UIRectEdgeNone;
}
}
override func viewDidLoad() {
// your code
if let nc = self.navigationController {
yourView.frame.origin.y = nc.navigationBar.frame.origin.y + nc.navigationBar.frame.height
}
}
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
// Fix up content offset to ensure the tableview isn't underlapping the status bar.
self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0.0, 0.0, 0.0);
}
class MyTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
configureTableViewTop()
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
coordinator.animateAlongsideTransition({ (context) -> Void in
}, completion: { (context) -> Void in
self.configureTableViewTop()
})
}
func configureTableViewTop() {
tableView.contentInset.top = UIApplication.sharedApplication().statusBarFrame.height
}
}
class MYCustomTableView: UITableView
{
override func drawRect(rect: CGRect) {
super.drawRect(rect)
contentInset = UIEdgeInsetsZero
}
}
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let insets = UIEdgeInsets(top: statusBarHeight, left: 0, bottom: 0, right: 0)
tableView.contentInset = insets
tableView.scrollIndicatorInsets = insets
private var statusBarMaskView: UIView!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let superview = self.tableView.superview {
self.statusBarMaskView = UIView(frame: CGRect.zero)
superview.insertSubview(self.statusBarMaskView, aboveSubview: self.tableView)
self.statusBarMaskView.backgroundColor = self.tableView.backgroundColor
// using a nice constraint layout library to set the frame
self.statusBarMaskView.pinTop(to: superview)
self.statusBarMaskView.pinLeft(to: superview)
self.statusBarMaskView.pinRight(to: superview)
self.statusBarMaskView.addHeightConstraint(with: 22.0)
////
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.statusBarMaskView.removeFromSuperview()
self.statusBarMaskView = nil
}