Iphone 在iOS上隐藏状态栏的正确方法,包括动画和调整根视图的大小
考虑一个视图控制器,它需要在单击按钮时滑出(或隐藏)状态栏Iphone 在iOS上隐藏状态栏的正确方法,包括动画和调整根视图的大小,iphone,ios,uiviewcontroller,statusbar,uistatusbar,Iphone,Ios,Uiviewcontroller,Statusbar,Uistatusbar,考虑一个视图控制器,它需要在单击按钮时滑出(或隐藏)状态栏 - (void) buttonClick:(id)sender { [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; } 上面的内容有效地隐藏了状态栏,但没有适当地调整根视图的大小,在顶部留下
- (void) buttonClick:(id)sender
{
[[UIApplication sharedApplication] setStatusBarHidden:YES
withAnimation:UIStatusBarAnimationSlide];
}
上面的内容有效地隐藏了状态栏,但没有适当地调整根视图的大小,在顶部留下20像素的间隙
我所期望的是根视图在状态栏以前使用的空间上展开(已设置动画,与状态栏动画的持续时间相同)
这样做的正确方式是什么
(我知道有很多类似的问题,但我找不到任何关于按需隐藏状态栏的信息,而不是隐藏状态栏以显示新的视图控制器的信息)
“蛮力”方法
显然,下面的工作
[[UIApplication sharedApplication] setStatusBarHidden:YES
withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:0.25 animations:^{
CGRect frame = self.view.frame;
frame.origin.y -= 20;
frame.size.height += 20;
self.view.frame = frame;
}];
……但也有缺点:
- 硬编码幻灯片动画的持续时间
- 硬编码状态栏的高度
- 根视图原点保持在(0,-20)。我希望帧尽可能从(0,0)开始
- 确保根视图的自动调整大小掩码具有
和UIViewAutoresizingFlexibleTopMargin
UIViewAutoresizingFlexibleHeight
- 隐藏状态栏后调用了
[self.view setNeedsLayout]
- 隐藏状态栏后调用了
[self.view setNeedsDisplay]
- 在隐藏状态栏之前和之后,将
设置为wantsFullScreenLayout
YES
self.wantsFullScreenLayout=YES
在您的视图中加载
,并将您的xib文件设置为屏幕大小(对于iPhone5为320x480和320x568)。但这意味着状态栏下的区域也不可见。使用这种方式,当您隐藏状态栏时,视图也不会展开。如果在状态栏区域没有显示的东西,你可以考虑这个方法。 < P>这是很好的,没有任何强>硬编码< /强> < /P>
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:0.25 animations:^{
self.navigationController.navigationBar.frame = self.navigationController.navigationBar.bounds;
self.view.window.frame = CGRectMake(0, 0, appFrame.size.width, appFrame.size.height);
}];
隐藏或显示同时调整视图大小的状态栏:
-(void)statusBar:(BOOL)status {
UIViewController *rootViewController = self.view.window.rootViewController;
UIView *view = rootViewController.view;
// Hide/Unhide the status bar
[[UIApplication sharedApplication] setStatusBarHidden:status]; // BOOL : YES or NO
// statusBar frame
CGRect statusBarFrame = [UIApplication.sharedApplication statusBarFrame];
// Establish baseline frame
CGRect newViewFrame = self.view.window.bounds;
// Check statusBar frame is worth dodging
if (!CGRectEqualToRect(statusBarFrame, CGRectZero)) {
UIInterfaceOrientation currentOrientation = rootViewController.interfaceOrientation;
if (UIInterfaceOrientationIsPortrait(currentOrientation)) {
// If portrait need to shrink height
newViewFrame.size.height -= statusBarFrame.size.height;
if (currentOrientation == UIInterfaceOrientationPortrait) {
// If not upside-down move down origin
newViewFrame.origin.y += statusBarFrame.size.height;
}
} else { // Is landscape
// portrait shrink width
newViewFrame.size.width -= statusBarFrame.size.width;
if (currentOrientation == UIInterfaceOrientationLandscapeLeft) {
// If the status bar is on the left side of the window move origin
newViewFrame.origin.x += statusBarFrame.size.width;
}
}
}
view.frame = newViewFrame; // pass new frame
}
调用方法(消息):
在花费数小时的实验和寻找答案之后;尤其通过一点调整,我已经成功地做到了,现在顶部间隙20px在过渡之间消失了 假设我们有一个BOOL
isStatusBarEnabled
ivar,它将指示我们是否应该隐藏状态栏(例如:在访问NSUserDefault
以检查boolValueForKey
时)
因此,我们首先通过[[UIApplication sharedApplication]isStatusBarHidden]
检查statusBar是否已隐藏,如果它未隐藏(=正在显示),我们将其隐藏!否则,就做别的
- 要在显示状态时修复20px,但导航未正确按下,只需在
self.navgigationController.navigationBar.frame的
中添加20点即可origin.y
- 当我们想隐藏状态栏时,也要这样做,只需删除
self.navgigationController.navigationBar.frame的
的20点,所以只需将其保留origin.y
0
@implementation SomeViewController {
BOOL isStatusBarEnabled;
}
// ...
- (void)toggleStatusBar
{
UINavigationBar *navBar = self.navigationController.navigationBar;
if ([[UIApplication sharedApplication] isStatusBarHidden]) {
// Change to regular mode
// Show status bar
[[UIApplication sharedApplication] setStatusBarHidden:NO
withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:0.3
animations:^{
navBar.frame = CGRectMake(navBar.frame.origin.x, 20, navBar.frame.size.width, navBar.frame.size.height);
} completion:nil];
} else if (![[UIApplication sharedApplication] isStatusBarHidden]) {
// Change to fullscreen mode
// Hide status bar
[[UIApplication sharedApplication] setStatusBarHidden:YES
withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:0.4
animations:^{
navBar.frame = CGRectMake(navBar.frame.origin.x, 0, navBar.frame.size.width, navBar.frame.size.height);
} completion:nil];
}
}
// ...
。。。然后,在我的例子中,我有一个设置键,让用户选择切换显示/隐藏状态栏
// ...
- (void)onDefaultsChanged:(NSNotification*)aNotification
{
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
isStatusBarEnabled = [standardDefaults boolForKey:kStatusBar];
if (isStatusBarEnabled) {
if ([[UIApplication sharedApplication] isStatusBarHidden]) {
// Change to regular mode
// Show status bar
[self toggleStatusBar];
} else {
// Change to fullscreen mode
// Hide status bar
[self toggleStatusBar];
}
// ...
}
就这样 您可以显示然后关闭模态视图控制器以正确隐藏状态栏
- (void)toggleStatusBar {
BOOL isStatusBarHidden = [[UIApplication sharedApplication] isStatusBarHidden];
[[UIApplication sharedApplication] setStatusBarHidden:!isStatusBarHidden];
UIViewController *vc = [[UIViewController alloc] init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
[vc release];
}
我在“WillAnimateRotationInterfaceOrientation”的横向定向方法中使用了这段代码,一切都正常工作。但是我不知道它是否能用于动画。对于那些试图使用基于视图控制器的状态栏外观实现此功能的人,您需要在视图控制器中实现prefersStatusBarHidden方法
-(BOOL)首选StatusBarHidden
{
//如果self.statusBarHidden为TRUE,则返回YES。如果为FALSE,则返回NO。
返回(self.statusBarHidden)?是:否;
}
然后,在按钮单击方法中:
-(无效)按钮单击:(id)发件人
{
//开关布尔值
self.statusBarHidden=(self.statusBarHidden)?否:是;
//更新状态栏
[UIView animateWithDuration:0.25动画:^{
[self-setNeedsStatusBarAppearanceUpdate];
}];
}
要设置动画样式,请使用以下命令:
-(UIStatusBarAnimation)首选状态栏更新映像
{
返回UIStatusBarAnimationSlide;
}
要自定义样式,请执行以下操作:
-(UIStatusBarStyle)首选状态BarStyle
{
返回UIStatusBarStyleLightContent;
}
为方便起见,@awfulcode答案的Swift 4变体:
var statusBarHidden = false {
didSet {
UIView.animate(withDuration: 0.25) {
self.setNeedsStatusBarAppearanceUpdate()
}
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .default
}
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .fade
}
override var prefersStatusBarHidden: Bool {
return statusBarHidden
}
谢谢@Lefteris。我很快就会查出来。但是,它会对动画持续时间进行硬编码。AFAIK,无法获取状态栏动画持续时间。您可以通过订阅键盘willshow/willhide通知来获取键盘动画持续时间,但不能订阅UIStatusBar。此外,iOS中似乎存在一个从未修复的bug,当状态栏隐藏或显示时,UIApplicationIDChangeStatusBarFrameNotification/UIApplicationWillChangeStatusBarFrameNotification不会被触发…嗨。。我有两个选项卡的tabbar应用程序。我只想隐藏第二个选项卡状态栏,但如果我这样做,我的第一个选项卡状态栏也将隐藏。如何修复?@GajendraKChauhan每个窗口只有一个状态栏,这意味着每个应用程序也有一个状态栏。嵌套控制器不起作用。但这是一个很好的方法。它也可以这样做:self.view.window.height+=statusBarHiddenState-20 : 20; (如果控制器管理状态栏)。孩子控制器仍然有问题。太好了。它起作用了。不知道为什么。这似乎是一个简单的黑客攻击。这是一个更好的答案。在iOS 7中不推荐使用WantFullScreenLayout,可能重复推荐和测试的方法。谢谢不要认为
[UIView animateWithDuration…]
在这里有任何价值;至少在iOS 13上运行时不会。UIStatusBarAnima
var statusBarHidden = false {
didSet {
UIView.animate(withDuration: 0.25) {
self.setNeedsStatusBarAppearanceUpdate()
}
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .default
}
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .fade
}
override var prefersStatusBarHidden: Bool {
return statusBarHidden
}