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

137

В моем файле .plist для параметра « Просмотр отображения строки состояния на основе контроллера » установлено значение NO. Но после UIImagePickerControllerэтого мое приложение ведет себя так, как если бы опция была установлена ​​на YES.

В своем приложении я представляю VC с расширением UIImagePickerController.

Проблема бывает так:

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

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

Alex L
источник
В моем случае ответ был привязан к childviewcontrollers. Мне пришлось воссоздать их, а не использовать повторно.
Alex L
7
Это действительно похоже на ошибку iOS 7. Кто-нибудь подавал отчет в Apple?
Dan F
stackoverflow.com/questions/21225978/… аналогичный вопрос с простым решением
Тинг Ву
Привет, @AlexL, ты знаешь, почему это происходит?
Шабаринатх Пабба

Ответы:

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 я обнаружил, что в некоторых случаях вам нужно ТАКЖЕ включить 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...

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

dpjanes
источник
3
Это уловка (как сказал Rich86man): «Поскольку UIImagePickerController - это тип контроллера навигации, вы также устанавливаете себя в качестве делегата UINavigationController».
Beto
2
а что после увольнения UIImaegPicker ..? Я установил скрытие строки состояния false, тогда фон станет черным.
Нитин Гохель
У вас настроен plist в соответствии с указанным выше вопросом?
dpjanes
Вы заметили проблему при использовании UIImagePickerControllerSourceTypePhotoLibrary, открыв какой-то альбом, а затем немного повернувшись назад и отменив жест?
Kukosk
3
Это работает, хотя строка состояния появляется и исчезает очень рывками. Я зарегистрировал ошибку в Apple.
jjxtra
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 любым стилем, который вам нужен.

Rich86man
источник
10

Принятый ответ будет работать, если для параметра «Просмотр внешнего вида строки состояния на основе контроллера» установлено значение «НЕТ» в файле .plist. Если вам действительно нужно управлять строкой состояния в некоторых других контроллерах представления и для этого параметра установлено значение 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];

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

Джесси Тайлер
источник
3

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

Пример здесь https://stackoverflow.com/a/19211669

Это решение мне подходит.

serj
источник
2

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

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

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

Йонас
источник
2

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

}
Панки
источник
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;
d.ennis
источник
2

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

Я представляю 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;
}];
Михаил Варбанов
источник
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
SoftDesigner
источник
1

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

Пепельная борозда
источник
Вероятно, это ошибка - я бы отправил радар с примером проекта и вернулся бы к старой системе управления строкой состояния :(
Ash Furrow
1

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

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

в ViewController, которые вызывают UIImagePickerController, и установите «View controller-based status bar appearance = NO» в файле plist. Надеюсь, это поможет.

jxdwinter
источник
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 представляет свое представление, я устанавливаю стиль строки состояния по умолчанию, поскольку цвет фона по умолчанию - светло-серый.

- (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;
}
JosephH
источник
1

Итак, у меня была эта проблема, и я смог решить ее, просто реализовав одну функцию делегата. Фон моей строки состояния черный, поэтому UIStatusBarStyle для моего приложения - .LightContent. Когда я представил UIImagePickerController для выбора фотографии из хранилища устройства, строка состояния была в порядке. Однако при нажатии на каталог, такой как «Фотопленка» или «Избранное», при эффективном нажатии на стек навигации, строка состояния исчезает. При выборе фото вообще не было строки состояния; при отключении другого контроллера модального представления присутствовала только батарея, что указывает на то, что остальная часть строки состояния также может быть черной.

Я пробовал некоторые другие решения, такие как расширение UIImagePickerController, но в Swift вы не можете переопределить использование расширений. Затем я попытался создать подкласс UIImagePickerController и попытался скрыть его строку состояния на viewWillAppear () и отобразить строку состояния на viewWillDisappear. Мне удалось увидеть скрытие строки состояния с помощью анимации .Slide, но поскольку строка состояния была невидимой при выборе каталога, я не смог увидеть скрытую строку состояния. Опять же, зеленая батарея вернулась, а остальная часть строки состояния стала невидимой после закрытия модального контроллера представления. Я также попытался переопределить prefersStatusBarHidden (), но эта функция никогда не вызывалась, поэтому я попытался вызвать setNeedsStatusBarAppearanceUpdate (), чтобы убедиться, что система вызывает prefersStatusBarHidden (), но она все еще не вызывается. Также, предлагается скрыть строку состояния в методе делегата 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)
    }
SwiftMatt
источник
-1

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

Андре Луис Алвес
источник