在iOS 7中,UIStatusBar被设计成这样,它与视图合并:
(GUI由Tina tavvar设计)
It is cool, but it will somewhat mess up your view when you have something at the top part of your view, and it becomes overlapped with the status bar.
Is there a simple solution (such as setting a property in info.plist) that can change the way it works [not overlapping] back to how it is in iOS6?
I know a more straightforward solution is to have self.view.center.x + 20 points for every single view controller, but changing them will screw other dimensions up (having a different self.view.center.x can cause problem to custom segues, etc.) and suddenly it turns into a tedious job that is best to be avoided.
I'll really be glad if someone can provide me an one-liner solution for this.
附注:我知道我可以隐藏状态栏
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
在didFinishLaunchingWithOptions方法中,但这是一个变通方法,一个避免问题的快捷方式,所以我不认为这是一个真正的解决方案。
因为使用presentViewController:animated:completion:把window.rootViewController弄乱了。因此,我必须找到一个不同的方法来解决这个问题。我终于让它与模态和旋转工作通过子类化我的rootViewController的UIView。
.h
@interface RootView : UIView
@end
.m
@implementation RootView
-(void)setFrame:(CGRect)frame
{
if (self.superview && self.superview != self.window)
{
frame = self.superview.bounds;
frame.origin.y += 20.f;
frame.size.height -= 20.f;
}
else
{
frame = [UIScreen mainScreen].applicationFrame;
}
[super setFrame:frame];
}
- (void)layoutSubviews
{
self.frame = self.frame;
[super layoutSubviews];
}
@end
现在你有了iOS7动画的强大解决方案。
我的解决方案是在iOS 7上,在窗口顶部添加一个高度为20点的UIView。
然后我在AppDelegate类中创建了一个方法来显示/隐藏“固态”状态栏背景。在应用程序:didFinishLaunchingWithOptions::
// ...
// Add a status bar background
self.statusBarBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width, 20.0f)];
self.statusBarBackground.backgroundColor = [UIColor blackColor];
self.statusBarBackground.alpha = 0.0;
self.statusBarBackground.userInteractionEnabled = NO;
self.statusBarBackground.layer.zPosition = 999; // Position its layer over all other views
[self.window addSubview:self.statusBarBackground];
// ...
return YES;
然后我创建了一个方法来淡入/淡出黑色状态栏背景:
- (void) showSolidStatusBar:(BOOL) solidStatusBar
{
[UIView animateWithDuration:0.3f animations:^{
if(solidStatusBar)
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
self.statusBarBackground.alpha = 1.0f;
}
else
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
self.statusBarBackground.alpha = 0.0f;
}
}];
}
我现在要做的就是在需要时调用[appDelegate showSolidStatusBar:YES]。
如果你正在使用接口构建器,试试这个:
在你的xib文件中:
1)选择主视图,设置背景颜色为黑色(或任何你想要状态栏的颜色)
2) Make sure the background is a self contained subview positioned as a top level child of the controller's view.
Move your background to become a direct child of the controller's view. Check the autosizing panel to be sure that you've locked all frame edges, activated both flexibility axes, and if this is a UIImageView, set the content mode to Scale to fill. Programmatically this translates to contentMode set to UIViewContentModeScaleToFill and has its auto resizing mask set to (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight).
3)现在将所有被锁定的东西上下移动20点,并设置iOS 6/7 delta Y为-20。
在自动缩放面板中,所有被锁定在顶部框架上的顶级子图层都需要向下移动20点,并将其iOS 6/7 delta Y设置为-20。(Cmd选择所有这些,并按下箭头20次-有更好的方法吗?)
4) Adjust the iOS 6/7 delta height of all of the above items that had a flexible height.
Any of the items that were locked to the frame top and bottom and had flexible height enabled in the autosizing panel must also have their iOS 6/7 delta height set to 20. That includes the background view mentioned above. This may seem anti-intuitive, but due to the order in which these are applied, it is necessary. The frame height is set first (based on device), then the deltas are applied, and finally the autosizing masks are applied based upon the offset positions of all of the child frames - think it through for a bit, it will make sense.
5)最后,被锁定在底部框架而不是顶部框架的项目根本不需要delta。
这将给你在iOS7和iOS6中相同的状态栏。
另一方面,如果你想要iOS7样式同时保持iOS6兼容性,那么将背景视图的delta Y / delta height值设置为0。
要查看更多iOS7迁移信息,请阅读全文:http://uncompiled.blogspot.com/2013/09/legacy-compatible-offsets-in-ios7.html
因为使用presentViewController:animated:completion:把window.rootViewController弄乱了。因此,我必须找到一个不同的方法来解决这个问题。我终于让它与模态和旋转工作通过子类化我的rootViewController的UIView。
.h
@interface RootView : UIView
@end
.m
@implementation RootView
-(void)setFrame:(CGRect)frame
{
if (self.superview && self.superview != self.window)
{
frame = self.superview.bounds;
frame.origin.y += 20.f;
frame.size.height -= 20.f;
}
else
{
frame = [UIScreen mainScreen].applicationFrame;
}
[super setFrame:frame];
}
- (void)layoutSubviews
{
self.frame = self.frame;
[super layoutSubviews];
}
@end
现在你有了iOS7动画的强大解决方案。
下面是广泛使用Storyboard的项目的另一种方法:
目标:
这种方法的目标是在iOS7中重新创建与在iOS6中相同的状态栏样式(见问题标题“iOS7状态栏回到iOS6样式?”)。
简介:
为了实现这一点,我们尽可能多地使用故事板,通过向下移动状态栏重叠的UI元素(在iOS 7下),同时使用增量来恢复iOS 6.1或更早版本的向下布局更改。在ios7中产生的额外空间然后被一个UIView占用,并将backgroundColor设置为我们选择的颜色。后者可以在代码中创建,也可以使用故事板(参见下面的替代方案)
假设:
为了在执行以下步骤时获得所需的结果,假设基于视图控制器的状态栏外观被设置为NO,并且您的状态栏样式被设置为“透明黑色样式(alpha of 0.5)”或“不透明黑色样式”。这两种设置都可以在项目设置的“信息”下找到或添加。
步骤:
Add a subview to the UIWindow to serve as your status bar background. To achieve this, add the following to your AppDelegate's application: didFinishLaunchingWithOptions: after makeKeyAndVisible
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
UIView *statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourAppsUIWindow.frame.size.width, 20)];
statusBarBackgroundView.backgroundColor = [UIColor blackColor];
[yourAppsUIWindow addSubview:statusBarBackgroundView];
}
Since you programmatically added a background for iOS 7 ONLY, you will have to adjust the layout of your UI elements that are overlapped by the status bar accordingly whilst preserving their layout for iOS6. To achieve this, do the following:
Ensure that Use Autolayout is unchecked for your Storyboard (this is because otherwise "iOS 6/7 Deltas" is not shown in the Size Inspector). To do this:
select your Storyboard file
show Utilities
select "Show the File Inspector"
Under "Interface Builder Document" uncheck "Use Autolayout"
Optionally, to help you monitor the layout changes for both iOS 7 AND 6 as you apply them, select the "Assistant Editor", select "Preview" and "iOS 6.1 or earlier":
Now select the UI element you want to adjust so it isn't overlapped by the status bar anymore
Select "Show the Size Inspector" in the Utilities column
Reposition your UI element along the Y-axis by the same amount as the statusbar bg height:
And change the iOS6/7 Deltas value for Y by the same NEGATIVE amount as the statusbar bg height (Note the change in the iOS 6 preview if you're using it):
选择:
为了在故事板繁重的项目中添加更少的代码,并让状态栏背景自动旋转,而不是以编程方式为状态栏添加背景,你可以为每个视图控制器添加一个彩色视图,位于所称视图控制器的主视图的最顶部。然后你将改变这个新视图的高度delta为与你的视图高度相同的负数(使它在iOS 6下消失)。
这个替代方案的缺点(尽管考虑到自旋转兼容性可能可以忽略不计)是,如果你在iOS 6中查看你的故事板,这个额外的视图不会立即可见。如果你看了一下故事板的“文档大纲”,你就会知道它在那里。