UIImagePickerController破坏状态栏外观


137

在我的.plist文件中,将“ 基于视图控制器的状态栏外观 ”设置为NO。但是之后UIImagePickerController,我的应用程序的行为就好像该选项设置为YES

在我的应用程序中,我呈现了一个VC,该VC呈现了一个UIImagePickerController

问题是这样发生的:

  • 呈现照片选择器后,选择照片库后,状态栏文本的颜色将更改。
  • 然后,一旦UIImagePickerController解散,状态栏的间距就会更改,而我其余应用程序的状态都会更改,其他控制器的所有导航栏都会显示在状态栏下。

有没有一种方法可以解决此问题,而无需在视图控制器中管理状态栏?


在我的案例中,答案与childviewcontroller有关。我不得不重新创建它们,而不是重复使用它们。
Alex L

7
这似乎确实是一个iOS 7错误,有人向Apple提交过报告吗?
Dan F

stackoverflow.com/questions/21225978/…与简单解决方案类似的问题
Ting Wu

嘿@AlexL,你知道为什么会这样吗?
Shabarinath Pabba

Answers:


192

上面的解决方案都不适合我,但是通过结合Rich86man和iOS_DEV_09的答案,我得到了一个始终如一的解决方案:

UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
}

关于这个很棒的解决方案。对于2014 / iOS8,我发现在某些情况下您还需要包括prefersStatusBarHiddenchildViewControllerForStatusBarHidden因此,...

-(void)navigationController:(UINavigationController *)navigationController
        willShowViewController:(UIViewController *)viewController
        animated:(BOOL)animated
    {
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    }

-(BOOL)prefersStatusBarHidden   // iOS8 definitely needs this one. checked.
    {
    return YES;
    }

-(UIViewController *)childViewControllerForStatusBarHidden
    {
    return nil;
    }

-(void)showCamera
    {
    self.cameraController = [[UIImagePickerController alloc] init];
    self.cameraController.delegate = (id)self; // dpjanes solution!
    etc...

希望对别人有帮助


3
这就是窍门(正如Rich86man所说):“由于UIImagePickerController是一种导航控制器,因此您也将自己设置为UINavigationController委托。”
Beto

2
解雇UIImaegPicker后如何处理?我将状态栏设置为false,然后将其背景变为黑色。
Nitin Gohel 2014年

您是否按照上述问题设置了plist?
dpjanes 2014年

使用UIImagePickerControllerSourceSourcePhotoPhotoLibrary,打开一些相册然后平移一下并取消手势时,您是否注意到问题?
库斯科斯克2014年

3
这是可行的,尽管状态栏以非常生硬的方式弹出。我已经向Apple提出了错误。
jjxtra 2014年

84

我今天也遇到了同样的问题。这是我的解决方案。

在调用图像选择器的视图控制器中,将您自己设置为图像选择器的委托。(您可能已经在这样做)

UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;

由于UIImagePickerController是一种导航控制器,因此您还需要将自己设置为UINavigationController委托。然后 :

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

用所需的样式替换UIStatusBarStyleLightContent。


10

如果您在.plist文件中将“基于View Controller的状态栏外观”设置为NO,则可接受的答案将起作用。如果确实需要在某些其他视图控制器中控制状态栏并将此选项设置为YES,则使UIImagePickerController正确运行的另一种方法是将其子类化

// .h
@interface MYImagePickerController : UIImagePickerController
@end

// .m
@implementation MYImagePickerController
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent; // change this to match your style
}
@end

6

我面临着同样的问题。

这是我的解决方案。将其放在要打开图像选择器视图的视图控制器的viewWillAppear中

-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];

[[UIApplication sharedApplication] setStatusBarHidden:YES];

}

4

你可以试试这个吗 我认为needsStatusBarApperanceUpdate将起作用。

1 -Set UIViewControllerBasedStatusBarAppearance to NO.
2- Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
3- [self setNeedsStatusBarAppearanceUpdate];

4

我发现这可以提供适当的处理,分为两个部分。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
}


- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
...

UIImagePickerController本身呈现视图控制器,因此此委托适用于堆栈上的所有呈现器。

viewWillAppear确保无论何时出现的视图控制器在其上方消失时,总是将其重置。



2

这可能是一个错误。我通过将“基于视图控制器的状态栏外观”设置为YES并在每个视图控制器中粘贴以下代码来解决了该问题:

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

然后,我的应用程序将按预期运行。


2

为了在UIImagePicker中隐藏状态栏:

--

 (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

当关闭UIImagePicker以隐藏View控制器中的状态栏时,请使用以下代码:

-(void) viewWillAppear:(BOOL)animated{
    [super viewWillAppear:YES];

    [[UIApplication sharedApplication] setStatusBarHidden:YES];

}

2

试试这个 ....

这在两种情况下都将起作用,即是否使用presentModalViewController和pushViewController

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;

委托方法

-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [picker dismissViewControllerAnimated:YES completion:^{}];
}


- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [picker dismissViewControllerAnimated:YES completion:nil];
}

2

以上所有都不适合我。我通过将演示样式更改为以下方式解决了该问题:

imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;

2

以上解决方案均不适合我。

我介绍UIImagePickerController作为模式视图控制器。取消UIImagePickerController后,状态栏状态为:

[UIApplication sharedApplication].statusBarOrientation = 0 (UIDeviceOrientationUnknown)
[UIApplication sharedApplication].statusBarFrame = { 0, 0, 0, 0}

对我来说解决此问题的解决方案是在关闭UIImagePickerController之后恢复statusBarOrientation:

UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
[self.viewController presentViewController:cameraUI animated:true completion:^(void){ }];

...

[self.viewController dismissViewControllerAnimated:animated completion:^(void){
    [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
}];

2

此代码帮助我自定义状态栏样式。

编辑:如果“查看基于控制器的状态栏外观” ==是,则此解决方案有效

@implementation UIImagePickerController (IOS7_StatusBarStyle)

-(UIViewController*)childViewControllerForStatusBarStyle
{
   return nil;
}

-(UIStatusBarStyle)preferredStatusBarStyle
{
   return UIStatusBarStyleLightContent;
}

@end

2

以上所有答案都可以,可以为您提供帮助。

我必须管理在不同iOS版本下运行的应用程序时遇到相同的问题。

UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];

if(IS_IOS8_AND_UP) {
    imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
} else {
    imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
}

imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:nil];

然后,在委托中:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    /* Cancel button color  */
    _imagePicker.navigationBar.tintColor = <custom_color>
    /* Status bar color */
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
}

2

在某些情况下可能仍然有效的另一种解决方案。

let imagePicker =  UIImagePickerController()
imagePicker.sourceType = .PhotoLibrary
imagePicker.navigationBar.barStyle = .Black

1

[self setNeedsStatusBarAppearanceUpdate]您呈现的视图控制器重新出现时是否尝试过呼叫?


那时可能是一个错误–我将用一个示例项目提交雷达,然后退回到管理状态栏的旧系统:(
Ash Furrow 2013年

1

我尝试在iOS7中的UIImagePickerController中隐藏状态栏,但我仍然不知道该怎么做。我用

- (void)viewWillAppear:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES
                                        withAnimation:UIStatusBarAnimationNone];
}

在调用UIImagePickerController的ViewController中,并在plist文件中设置“基于View Controller的状态栏外观= NO”。希望这会有所帮助。


1

试试这个 :

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;

在协议工具中,使用以下命令:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
}

1

这为我解决了...:

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [picker dismissViewControllerAnimated:YES completion:nil];
}

1

这里没有任何东西可以解决我所遇到的问题(也许OP也有),因此我想我会分享我的答案。而不是隐藏状态栏,我认为这是一个有问题的解决方案(我注意到它有时会使我的应用处于状态栏被隐藏的状态,而不应该隐藏它)。相反,我选择尝试并与它玩得很好UIStatusBarStyles

当呈现UIImagePickerController的视图时,我将状态栏样式设置为default,因为默认的背景色是浅灰色。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
}

然后,关闭图像选择器后,将其重新设置为UIStatusBarStyleLightContent

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //work

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

    [self dismissViewControllerAnimated:YES completion:NULL];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{ 
    //work

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

    [self dismissViewControllerAnimated:YES completion:NULL];
}

1

在这种情况下,我们使用2个步骤

第一步:在info.plist中添加:“基于视图控制器的状态栏外观”,值为“ NO”

在第二步中:与UIImagePickerController的委托一起使用/调用此代码

 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
     if([navigationController isKindOfClass:[UIImagePickerController class]])
         [[UIApplication sharedApplication] setStatusBarHidden:YES]; 
 }

如果是IOS-7,请增加一个功能

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

1

从iOS 8.1开始,看来他们终于解决了这个错误!我能够从代码中删除我采用的所有变通方法。


1

使用默认的iOS 8行为,当我希望隐藏状态栏时,状态栏出现问题。

我发现的解决方案是,直接presentPopover从我的视图控制器调用之后,我做了:

    [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate) withObject:nil afterDelay:0.01];

我还必须将其添加到我的主视图控制器中:

- (UIViewController *)childViewControllerForStatusBarHidden
{
    return nil;
}

1

因此,我遇到了这个问题,并且仅通过实现一个委托函数就可以解决它。我的状态栏的背景是黑色,因此我的应用程序的UIStatusBarStyle是.LightContent。当我展示UIImagePickerController以便从设备存储中选择照片时,状态栏很好。但是,在单击诸如“相机胶卷”或“收藏夹”之类的目录后,有效地推入导航堆栈时,状态栏消失了。选择照片后,根本没有状态栏。解散另一个模式视图控制器后,仅存在电池,表明状态栏的其余部分也可能是黑色的。

我尝试了其他一些解决方案,例如扩展UIImagePickerController,但是在Swift中,无法使用扩展覆盖。然后,我尝试继承UIImagePickerController的子类,并尝试在viewWillAppear()上隐藏其状态栏,并在viewWillDisappear上取消隐藏状态栏。我可以看到带有.Slide动画的状态栏隐藏,但是由于选择目录后看不到状态栏,因此无法取消隐藏状态栏。同样,绿色电池又回来了,关闭模式视图控制器后,状态栏的其余部分不可见。我还尝试覆盖了preferredsStatusBarHidden(),但从未调用该函数,因此我尝试调用setNeedsStatusBarAppearanceUpdate()以确保系统调用了preferredsStatusBarHidden(),但仍未调用它。也,建议将状态栏设置为隐藏在委托方法navigationController willShowViewController上。再次,所有这些操作就是隐藏状态栏,这不能解决问题。事实证明,状态栏样式似乎在推入UIImagePickerController的导航堆栈时已更改。为了完全解决问题,我不必编写扩展或UIImagePickerController的子类。您所需要做的就是设置委托并设置状态栏样式以保持不变。这样添加就好像问题从未存在过一样。似乎在推入UIImagePickerController的导航堆栈时,状态栏样式已更改。为了完全解决问题,我不必编写扩展或UIImagePickerController的子类。您所需要做的就是设置委托并设置状态栏样式以保持不变。这样添加就好像问题从未存在过一样。似乎在推入UIImagePickerController的导航堆栈时,状态栏样式已更改。为了完全解决问题,我不必编写扩展或UIImagePickerController的子类。您所需要做的就是设置委托并设置状态栏样式以保持不变。这样添加就好像问题从未存在过一样。

let pickerController = UIImagePickerController()
pickerController.delegate = self

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
        UIApplication.sharedApplication().setStatusBarStyle(.LightContent, animated: false)
    }

-1

我实际上找到了一种更好的方法来设置“图像选择器”中的状态栏背景颜色。基本上,您需要将navigationBar的backgroundImage设置为nil,因为Image Picker中的默认设置是将backgroundImage作为白色Image。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.