UIImagePickerController ломает внешний вид строки состояния

В моем файле.plist "Просмотр внешнего вида строки состояния на контроллере" установлен на NO, Но после UIImagePickerControllerмое приложение ведет себя так, как будто опция установлена YES,

В моем приложении я представляю VC, который представляет UIImagePickerController,

Проблема происходит так:

  • После представления средства выбора фотографий при выборе библиотеки фотографий цвет текста строки состояния меняется.
  • Потом однажды, UIImagePickerController удален, интервал строки состояния изменяется для остальной части моего приложения, и вся панель навигации для других контроллеров отображается под строкой состояния.

Есть ли способ решить эту проблему без управления строкой состояния в моих контроллерах представления?

25 ответов

Решение

Ни одно из вышеуказанных решений не помогло мне, но, объединив ответы 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...

Надеюсь, это поможет кому-то

Я столкнулся с этой же проблемой сегодня. Вот мое решение.

В контроллере представления, который вызывает средство выбора изображений, установите себя в качестве делегата средства выбора изображений. (Вы, вероятно, уже делаете это)

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 любым стилем, который вы ищете.

Принятый ответ будет работать, если в вашем файле.plist для параметра "Просмотр внешнего вида строки состояния на основе контроллера" установлено значение "NO". Если вам действительно нужно контролировать строку состояния в некоторых других контроллерах представления и установить для этой опции значение YES, другой способ заставить UIImagePickerController вести себя правильно - это создать его подклассы

// .h
@interface MYImagePickerController : UIImagePickerController
@end

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

Я столкнулся с той же проблемой.

вот мое решение. поместите это в viewWillAppear контроллера представления, из которого вы открываете представление выбора изображения

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

[[UIApplication sharedApplication] setStatusBarHidden:YES];

}

Я нашел это, чтобы предложить правильную обработку, есть две части.

- (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 гарантирует, что сам этот контроллер представления всегда сбрасывается всякий раз, когда текущий контроллер представления отклоняется над ним.

Можете ли вы попробовать это. Я думаю, что needsStatusBarApperanceUpdate будет работать.

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

У меня такая же проблема. Добавьте в информационный лист: "Просмотр внешнего вида строки состояния на основе контроллера" со значением "НЕТ"

Пример здесь /questions/529134/setstatusbarhidden-ne-rabotaet/529140#529140

Это решение работает для меня.

Еще одно решение, которое может работать в некоторых ситуациях.

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

Ни одно из вышеперечисленных решений не помогло мне.

Я представляю UIImagePickerController в качестве контроллера модального представления. После закрытия UIImagePickerController состояние строки состояния было:

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

Решением, которое решило проблему для меня, было восстановление statusBarOrientation после закрытия UIImagePickerController:

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

...

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

Этот код помог мне настроить стиль строки состояния.

РЕДАКТИРОВАТЬ: это решение работает, если "Показать внешний вид строки состояния на основе контроллера" == ДА

@implementation UIImagePickerController (IOS7_StatusBarStyle)

-(UIViewController*)childViewControllerForStatusBarStyle
{
   return nil;
}

-(UIStatusBarStyle)preferredStatusBarStyle
{
   return UIStatusBarStyleLightContent;
}

@end

Чтобы скрыть строку состояния в 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];

}

Это, вероятно, ошибка. Я решил проблему, установив для параметра "Вид строки состояния на основе контроллера" значение "YES" и вставив в каждый контроллер представления следующий код:

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

Тогда мое приложение ведет себя как ожидалось.

Попробуй это....

это будет работать в обоих случаях, т. е. используете ли вы 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];
}

Все вышеперечисленное не сработало для меня. Я решил проблему, изменив стиль презентации на:

imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;

Все ответы выше в порядке и могут помочь.

У меня была та же проблема, связанная с управлением приложением, запущенным под разными версиями 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];
}

Начиная с iOS 8.1 кажется, что они наконец исправили эту ошибку! Я смог удалить все используемые мной обходные пути из своего кода.

Я пытаюсь скрыть строку состояния в UIImagePickerController в iOS7, но я все еще не знаю, как это сделать. я использую

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

в ViewController, который вызывает UIImagePickerController, и установите "Просмотр внешнего вида строки состояния на основе контроллера = НЕТ" в файле plist. Надеюсь, это поможет.

Вы пробовали звонить [self setNeedsStatusBarAppearanceUpdate] когда ваш контроллер представления снова появляется?

Это решило это для меня...

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

Попробуй это:

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

и в реализации протокола используйте это:

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

Так что у меня была эта проблема, и я смог решить ее, просто внедрив одну делегатскую функцию. Фон моей строки состояния черный, поэтому 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)
    }

Ничто здесь конкретно не решало проблему в том, что у меня было (и, возможно, у ОП тоже), поэтому я подумала, что поделюсь своим ответом. Вместо того, чтобы скрывать строку состояния, которая, на мой взгляд, является ошибочным решением (я заметил, что иногда мое приложение оставлялось бы в состоянии, когда строка состояния была скрыта, когда этого не должно быть). Вместо этого я решил попробовать поиграть с 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];
}

При использовании поведения iOS 8 по умолчанию у меня были проблемы с появлением строки состояния, когда я хотел ее скрыть.

Решение, которое я нашел, состояло в том, что сразу после звонка presentPopover с моей точки зрения контроллер я сделал:

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

Я также должен был добавить это к моему главному контроллеру представления:

- (UIViewController *)childViewControllerForStatusBarHidden
{
    return nil;
}

В этом случае мы используем 2 шага

На первом шаге: Добавьте в info.plist: "Просмотр внешнего вида строки состояния на основе контроллера" со значением "НЕТ"

На втором этапе: используйте / вызовите этот код с делегатом 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;
}

На самом деле я нашел лучший способ установить цвет фона строки состояния в Image Picker. По сути, вам нужно установить backgroundImage из navigationBar в nil, потому что по умолчанию в Image Picker backgroundImage имеет вид белого изображения.

Другие вопросы по тегам