UIImagePickerController порушує зовнішній вигляд рядка стану


137

У моєму .plist файлі встановлено значення " Перегляд зовнішнього вигляду на основі контролера " NO. Але після цього UIImagePickerControllerмоє додаток поводиться так, ніби налаштовано параметр YES.

У своєму додатку я представляю ЖК, який представляє UIImagePickerController.

Проблема відбувається так:

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

Чи є спосіб вирішити це без керування рядком стану, на мій погляд, контролерами?


Відповідь у моєму випадку була прив’язана до контролерів дитячого контролю. Мені довелося відтворити їх, а не використовувати їх повторно.
Алекс Л

7
Це справді здається помилкою в iOS 7, хтось подав звіт в Apple?
Дан Ф

stackoverflow.com/questions/21225978/… подібне запитання з простим рішенням
Ting Wu

Привіт @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...

Сподіваюся, це комусь допоможе


3
Це хитрість (як сказав Rich86man): "Оскільки UIImagePickerController є типом контролера навігації, ви також встановлюєте себе як делегата UINavigationController."
Бето

2
а як бути після звільнення UIImaegPicker ..? Я встановлюю панель стану приховати помилкову, тоді фон переходить у чорний колір.
Нітін Гогель

Чи встановлений у вас пліст відповідно до вищезазначеного питання?
dpjanes

Ви помітили проблему під час використання UIImagePickerControllerSourceTypePhotoLibrary, відкривши якийсь альбом, а потім трохи повернувшись назад і скасувавши жест?
Кукоск

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 будь-яким стилем, який ви шукаєте.


10

Прийнята відповідь спрацює, якщо у вашому .plist файлі "Вид перегляду статусу на основі контролера" встановлено значення "НІ". Якщо вам дійсно потрібно керувати рядком стану в деяких інших контролерах перегляду та встановити цей параметр "ТАК", інший спосіб змусити 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

Ви можете спробувати це. Я думаю, що NeedStatusBarApperanceUpdate працюватиме.

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

Це рішення працює для мене.


2

Це, мабуть, помилка. Я вирішив проблему, встановивши "Перегляд вигляду рядка стану на основі контролера", встановленого на "ТАК", і в кожному контролері перегляду вставте наступний код:

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

Рішенням, яке вирішило проблему для мене, було відновлення статусуBarOrientation після відхилення 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

Цей код допоміг мені налаштувати стиль рядка стану.

EDIT: це рішення працює, якщо "Перегляд вигляду рядка стану на основі контролера" == ТАК

@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

1

Я намагаюся приховати рядок стану в UIImagePickerController в iOS7, але досі не знаю, як це зробити. я використовую

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

у ViewController, який викликає UIImagePickerController, і встановить "Перегляд зовнішнього вигляду рядка стану на основі контролера = НІ" у файлі списку. Сподіваюся, що це може допомогти.


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

Нічого тут конкретно не вирішило проблему в тому, що я мав (і, можливо, що в ОП теж було), тому я подумав, що поділюсь своєю відповіддю. Замість того, щоб ховати рядок стану, який, на мою думку, є помилковим рішенням (я помітив, що іноді він залишає моє додаток у стані, коли рядок стану приховано, коли його не повинно бути). Я замість цього вирішив спробувати грати добре з 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: "Переглянути зовнішній вигляд рядка стану контролера" зі значенням "НІ"

На другому кроці: Використовуйте / викликайте цей код з делегатом 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, але оскільки панель стану була невидимою при виборі каталогу, я не зміг побачити рядок стану. Знову зелений акумулятор повернувся з рештою панелі стану, невидимою після відключення контролера модального перегляду. Я також спробував переосмислити перевагуStatusBarHidden (), але цю функцію ніколи не викликали, тому я спробував викликати setNeedsStatusBarAppearanceUpdate (), щоб переконатися, що prefersStatusBarHidden () викликається системою, але вона все ще не називається. Також, є пропозиція встановити рядок стану прихованим методом делегата навігаціїController 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

Насправді я знайшов кращий спосіб встановити колір тла смуги стану в програмі Image Picker. В основному вам потрібно встановити backgroundImage з навігаціїBar на нуль, тому що за замовчуванням у Image Picker є backgroundImage як біле зображення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.