UIImagePickerController 打破状态栏的外观

Posted

技术标签:

【中文标题】UIImagePickerController 打破状态栏的外观【英文标题】:UIImagePickerController breaks status bar appearance 【发布时间】:2013-09-23 16:37:44 【问题描述】:

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

在我的应用中,我展示了一个 VC,它展示了一个 UIImagePickerController

问题是这样发生的:

呈现照片拾取器后,当挑选照片库时,状态栏文本的颜色更改。 然后有一次,UIImagePickerController被驳回,状态栏间距 我的应用其余部分的更改以及其他控制器的所有导航栏都显示在状态栏下方。

有没有办法在不管理视图控制器中的状态栏的情况下解决这个问题?

【问题讨论】:

我的答案与 childviewcontrollers 相关。我不得不重新创建它们而不是重复使用它们。 这看起来真的是 ios 7 的 bug,有没有人向 Apple 提交报告? ***.com/questions/21225978/… 类似问题的简单解决方案 嘿@AlexL,你知道为什么会这样吗? 【参考方案1】:

上述解决方案都不适合我,但通过结合 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,我发现在某些情况下您还需要包括 prefersStatusBarHidden 和可能的 childViewControllerForStatusBarHidden 所以...

-(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...

【讨论】:

这就是诀窍(正如 Rich86man 所说):“由于 UIImagePickerController 是一种导航控制器,因此您也将自己设置为 UINavigationController 委托。” 关闭 UIImaegPicker 后怎么样..?我将状态栏隐藏设置为 false 然后它的背景会变黑。 您是否按照上述问题设置了 plist? 您在使用 UIImagePickerControllerSourceTypePhotoLibrary 时是否注意到这个问题,打开一些相册,然后向后平移一点,然后取消手势? 这行得通,尽管状态栏以非常生涩的方式进出。我已经向 Apple 提交了一个错误。【参考方案2】:

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

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

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 替换为您要查找的任何样式。

【讨论】:

【参考方案3】:

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

// .h
@interface MYImagePickerController : UIImagePickerController
@end

// .m
@implementation MYImagePickerController
- (UIStatusBarStyle)preferredStatusBarStyle

    return UIStatusBarStyleLightContent; // change this to match your style

@end

【讨论】:

【参考方案4】:

我遇到了同样的问题。

这是我的解决方案。 把它放在你打开图像选择器视图的视图控制器的 viewWillAppear 中

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

[[UIApplication sharedApplication] setStatusBarHidden:YES];


【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

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

- (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 确保该视图控制器本身总是被重置,只要呈现的视图控制器在其上方消失。

【讨论】:

【参考方案7】:

我遇到了同样的问题。 添加信息 plist:“查看基于控制器的状态栏外观”,值为“NO”

这里的例子https://***.com/a/19211669

这个解决方案对我有用。

【讨论】:

【参考方案8】:

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

- (BOOL)prefersStatusBarHidden

    return YES;

然后我的应用会按预期运行。

【讨论】:

【参考方案9】:

用于隐藏 UIImagePicker 中的状态栏:

-

 (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

当 UIImagePicker 被解除以隐藏视图控制器中的状态栏时,请使用以下代码:

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

    [[UIApplication sharedApplication] setStatusBarHidden:YES];


【讨论】:

【参考方案10】:

试试这个....

这在两种情况下都有效,即是否使用 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];

【讨论】:

【参考方案11】:

以上所有对我都不起作用。我通过将演示样式更改为:

imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;

【讨论】:

【参考方案12】:

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

我将 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;
];

【讨论】:

【参考方案13】:

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

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

@implementation UIImagePickerController (IOS7_StatusBarStyle)

-(UIViewController*)childViewControllerForStatusBarStyle

   return nil;


-(UIStatusBarStyle)preferredStatusBarStyle

   return UIStatusBarStyleLightContent;


@end

【讨论】:

【参考方案14】:

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

我在管理在不同 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];

【讨论】:

【参考方案15】:

另一种解决方案可能适用于某些情况。

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

【讨论】:

【参考方案16】:

当您的呈现视图控制器重新出现时,您是否尝试过调用[self setNeedsStatusBarAppearanceUpdate]

【讨论】:

这可能是一个错误——我会用一个示例项目提交radar 并回退到管理状态栏的旧系统:(【参考方案17】:

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

- (void)viewWillAppear:(BOOL)animated

    [[UIApplication sharedApplication] setStatusBarHidden:YES
                                        withAnimation:UIStatusBarAnimationNone];

在调用UIImagePickerController的ViewController中,在plist文件中设置“View controller-based status bar appearance = NO”。希望这能有所帮助。

【讨论】:

【参考方案18】:

试试这个:

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

在协议实现中,使用这个:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated

    [[UIApplication sharedApplication] setStatusBarHidden:YES];

【讨论】:

【参考方案19】:

这为我解决了...:

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [picker dismissViewControllerAnimated:YES completion:nil];

【讨论】:

【参考方案20】:

这里没有什么特别解决我遇到的问题(也许 OP 也有),所以我想我会分享我的答案。而不是隐藏我认为是错误解决方案的状态栏(我注意到它有时会使我的应用程序处于状态栏不应该隐藏的状态)。相反,我选择尝试和UIStatusBarStyles 玩得很好。

当 UIImagePickerController 显示其视图时,我将状态栏样式设置为默认值,因为默认背景颜色是浅灰色。

- (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];

【讨论】:

【参考方案21】:

在这种情况下,我们使用 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;

【讨论】:

【参考方案22】:

从 iOS 8.1 开始,他们似乎终于修复了这个错误!我能够从我的代码中删除我使用的所有解决方法。

【讨论】:

【参考方案23】:

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

我找到的解决方案是,在我直接从视图控制器调用 presentPopover 之后:

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

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

- (UIViewController *)childViewControllerForStatusBarHidden

    return nil;

【讨论】:

【参考方案24】:

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

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

let pickerController = UIImagePickerController()
pickerController.delegate = self

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

【讨论】:

【参考方案25】:

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

【讨论】:

以上是关于UIImagePickerController 打破状态栏的外观的主要内容,如果未能解决你的问题,请参考以下文章

UIImagePickerController 不是全屏

UIImagePickerController、自定义 UIButton 和 AutoLayout

UIImagePickerController 实况照片

OCMock 模拟 UIImagePickerController

UIImagePickerController 图像没有改变

无法弹出 UIImagePickerController