UIImagePickerController przerywa wygląd paska stanu

137

W moim pliku .plist mam ustawioną opcję „ Wyświetl wygląd paska stanu na podstawie kontroleraNO. Ale potem UIImagePickerControllermoja aplikacja zachowuje się tak, jakby ta opcja była ustawiona na YES.

W mojej aplikacji przedstawiam VC, który przedstawia plik UIImagePickerController.

Problem wygląda tak:

  • Po zaprezentowaniu selektora zdjęć po wybraniu biblioteki zdjęć zmienia się kolor tekstu paska stanu.
  • Następnie, po UIImagePickerControllerodrzuceniu, odstępy między paskiem stanu zmieniają się dla reszty mojej aplikacji, a cały pasek nawigacji dla innych kontrolerów wyświetla się pod paskiem stanu.

Czy istnieje sposób na rozwiązanie tego problemu bez zarządzania paskiem stanu w moich kontrolerach widoku?

Alex L.
źródło
Odpowiedź w moim przypadku była związana z kontrolerami dzieci. Musiałem je odtworzyć, zamiast używać ich ponownie.
Alex L
7
To naprawdę wygląda na błąd w iOS 7, czy ktoś złożył raport w Apple?
Dan F
stackoverflow.com/questions/21225978/ ... podobne pytanie z prostym rozwiązaniem
Ting Wu
Hej @AlexL, czy wiesz, dlaczego tak się dzieje?
Shabarinath Pabba

Odpowiedzi:

192

Żadne z powyższych rozwiązań nie działało dla mnie, ale łącząc odpowiedzi Rich86man i iOS_DEV_09, otrzymałem konsekwentnie działające rozwiązanie:

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

i

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

Co do tego niesamowitego rozwiązania. W przypadku 2014 / iOS8 odkryłem, że w niektórych przypadkach musisz RÓWNIEŻ dołączyć prefersStatusBarHiddeni, być może, childViewControllerForStatusBarHiddenwięc ...

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

Mam nadzieję, że to komuś pomoże

dpjanes
źródło
3
Oto sztuczka (jak powiedział Rich86man): „Ponieważ UIImagePickerController jest typem kontrolera nawigacji, ustawiasz siebie również jako delegata UINavigationController”.
Beto
2
a co po zwolnieniu UIImaegPicker ..? Ustawiam statusbar hide na fałsz, wtedy jego tło będzie czarne.
Nitin Gohel,
Czy masz skonfigurowaną listę plist zgodnie z powyższym pytaniem?
dpjanes
Czy zauważyłeś problem podczas korzystania z UIImagePickerControllerSourceTypePhotoLibrary, otwierania jakiegoś albumu, a następnie przewijania do tyłu i anulowania gestu?
Kukosk
3
Działa to, chociaż pasek stanu pojawia się i wyskakuje w bardzo nierówny sposób. Zgłosiłem błąd w Apple.
jjxtra
84

Zmierzyłem się dzisiaj z tym samym problemem. Oto moje rozwiązanie.

W kontrolerze widoku, który wywołuje selektor obrazów, ustaw siebie jako delegata selektora obrazów. (Prawdopodobnie już to robisz)

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

Ponieważ UIImagePickerController jest typem kontrolera nawigacji, ustawiasz również siebie jako delegata UINavigationController. Następnie :

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

Zastąp UIStatusBarStyleLightContent dowolnym stylem, którego szukasz.

Rich86man
źródło
10

Zaakceptowana odpowiedź będzie działać, jeśli opcja „Wyświetl wygląd paska stanu na podstawie kontrolera” jest ustawiona na NIE w pliku .plist. Jeśli rzeczywiście potrzebujesz kontrolować pasek stanu w innych kontrolerach widoku i mieć tę opcję ustawioną na TAK, innym sposobem, aby UIImagePickerController zachowywał się poprawnie, jest tworzenie podklasy

// .h
@interface MYImagePickerController : UIImagePickerController
@end

// .m
@implementation MYImagePickerController
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent; // change this to match your style
}
@end
mgcm
źródło
6

stanąłem przed tym samym problemem.

oto moje rozwiązanie. umieść to w viewWillAppear kontrolera widoku, z którego otwierasz widok wyboru obrazu

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

[[UIApplication sharedApplication] setStatusBarHidden:YES];

}
iOS_DEV
źródło
4

Możesz tego spróbować. Myślę, że needStatusBarApperanceUpdate będzie działać.

1 -Set UIViewControllerBasedStatusBarAppearance to NO.
2- Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
3- [self setNeedsStatusBarAppearanceUpdate];
Burcu Geneci
źródło
4

Zauważyłem, że zapewnia to właściwą obsługę, składa się z dwóch części.

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

sam UIImagePickerController przedstawia kontrolery widoku, więc ten delegat działa dla wszystkich osób prowadzących na stosie.

viewWillAppear zapewnia, że ​​sam kontroler widoku jest zawsze resetowany za każdym razem, gdy kontroler widoku prezentacji zostanie zwolniony nad nim.

Jesse Tayler
źródło
3

Miałem ten sam problem. Dodaj listę informacji: „Wyświetl wygląd paska stanu opartego na kontrolerze” z wartością „NIE”

Przykład tutaj https://stackoverflow.com/a/19211669

To rozwiązanie działa na mnie.

serj
źródło
2

To prawdopodobnie błąd. Rozwiązałem problem, ustawiając „Wyświetl wygląd paska stanu na podstawie kontrolera” na TAK i w każdym widoku kontrolera wklejając w następującym kodzie:

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

Moja aplikacja zachowuje się wtedy zgodnie z oczekiwaniami.

Jonas
źródło
2

Aby ukryć pasek stanu w UIImagePicker:

-

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

a gdy UIImagePicker zostanie odrzucony, aby ukryć pasek stanu w kontrolerze View, użyj następującego kodu:

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

    [[UIApplication sharedApplication] setStatusBarHidden:YES];

}
Panky
źródło
2

Spróbuj tego ....

zadziała w obu przypadkach, tj. niezależnie od tego, czy używasz presentModalViewController i pushViewController

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

metody delegowania

-(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];
}
Shaik Riyaz
źródło
2

To wszystko nie działa dla mnie. Rozwiązałem problem, zmieniając styl prezentacji na:

imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
d.ennis
źródło
2

Żadne z powyższych rozwiązań nie zadziałało.

Przedstawiam UIImagePickerController jako kontroler widoku modalnego. Po zamknięciu UIImagePickerController stan paska stanu był następujący:

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

Rozwiązaniem, które rozwiązało ten problem, było przywrócenie statusuBarOrientation po zamknięciu UIImagePickerController:

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

...

[self.viewController dismissViewControllerAnimated:animated completion:^(void){
    [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
}];
Mihail Varbanov
źródło
2

Ten kod pomógł mi dostosować styl paska stanu.

EDYCJA: to rozwiązanie działa, jeśli „Wyświetl wygląd paska stanu na podstawie kontrolera” == TAK

@implementation UIImagePickerController (IOS7_StatusBarStyle)

-(UIViewController*)childViewControllerForStatusBarStyle
{
   return nil;
}

-(UIStatusBarStyle)preferredStatusBarStyle
{
   return UIStatusBarStyleLightContent;
}

@end
Igor Palaguta
źródło
2

Wszystkie powyższe odpowiedzi są w porządku i mogą pomóc.

Miałem ten sam problem z zarządzaniem aplikacją działającą pod różnymi wersjami 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];

Następnie w delegacie:

- (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];
}
Luca Davanzo
źródło
2

Jeszcze jedno rozwiązanie, które może się sprawdzić w niektórych sytuacjach.

let imagePicker =  UIImagePickerController()
imagePicker.sourceType = .PhotoLibrary
imagePicker.navigationBar.barStyle = .Black
SoftDesigner
źródło
1

Czy próbowałeś zadzwonić, [self setNeedsStatusBarAppearanceUpdate]gdy ponownie pojawi się kontroler widoku prezentacji?

Jesion Bruzda
źródło
To prawdopodobnie błąd - zgłosiłbym radar z przykładowym projektem i wrócił do starego systemu zarządzania paskiem stanu :(
Ash Furrow
1

Próbuję ukryć pasek stanu w UIImagePickerController w iOS7, ale nadal nie wiem, jak to zrobić. używam

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

w ViewController, które wywołują UIImagePickerController i ustawiają „Wyświetl wygląd paska stanu opartego na kontrolerze = NIE” w pliku plist. Mam nadzieję, że to pomoże.

jxdwinter
źródło
1

Spróbuj tego :

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

aw implementacji protokołu użyj tego:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
}
ouyongyong
źródło
1

To rozwiązało to dla mnie ...:

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [picker dismissViewControllerAnimated:YES completion:nil];
}
Seb OH
źródło
1

Nic tutaj nie rozwiązało problemu, który miałem (i być może, że OP też miał), więc pomyślałem, że podzielę się swoją odpowiedzią. Zamiast ukrywać pasek stanu, który moim zdaniem jest błędnym rozwiązaniem (zauważyłem, że czasami pozostawiał moją aplikację w stanie, w którym pasek stanu był ukryty, gdy nie powinien). Zamiast tego zdecydowałem się na dobrą zabawę z UIStatusBarStyles.

Kiedy UIImagePickerController ma swój widok, ustawiłem styl paska stanu na domyślny, ponieważ domyślnym kolorem tła jest jasnoszary.

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

Następnie, gdy selektor obrazów zostanie zamknięty, ustawiłem go z powrotem na 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];
}
Ian Hoar
źródło
1

W tym przypadku używamy 2 kroków

W pierwszym kroku: Dodaj w info.plist: „Wyświetl wygląd paska stanu na podstawie kontrolera” z wartością „NIE”

W drugim kroku: użyj / wywołaj ten kod z delegatem UIImagePickerController

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

W przypadku IOS-7 dodaj jeszcze jedną funkcję

- (BOOL)prefersStatusBarHidden
{
    return YES;
}
Vaibhav Sharma
źródło
1

Od wersji iOS 8.1 wygląda na to, że w końcu naprawili ten błąd! Udało mi się usunąć wszystkie zastosowane obejścia z mojego kodu.

Jeff V
źródło
1

Używając domyślnego zachowania iOS 8, miałem problemy z wyświetlaniem paska stanu, gdy chciałem go ukryć.

Rozwiązanie, które znalazłem, było takie, że bezpośrednio po wywołaniu presentPopoverz kontrolera widoku zrobiłem:

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

Musiałem też dodać to do mojego głównego kontrolera widoku:

- (UIViewController *)childViewControllerForStatusBarHidden
{
    return nil;
}
JosephH
źródło
1

Więc miałem ten problem i udało mi się go rozwiązać, po prostu implementując jedną funkcję delegata. Tło mojego paska stanu jest czarne, a więc UIStatusBarStyle dla mojej aplikacji to .LightContent. Kiedy przedstawiłem UIImagePickerController, aby wybrać zdjęcie z pamięci urządzenia, pasek stanu był w porządku. Jednak po kliknięciu katalogu, takiego jak „Rolka z aparatu” lub „Ulubione”, i efektywnym przeniesieniu na stos nawigacji, pasek stanu zniknął. Po wybraniu zdjęcia w ogóle nie było paska stanu; po odrzuceniu innego kontrolera widoku modalnego była obecna tylko bateria, co wskazuje, że pozostała część paska stanu może być również czarna.

Wypróbowałem kilka innych rozwiązań, takich jak rozszerzenie UIImagePickerController, ale w Swift nie można nadpisać za pomocą rozszerzeń. Następnie próbowałem podklasować UIImagePickerController i próbowałem ukryć jego pasek stanu w viewWillAppear () i odkryć pasek stanu w viewWillDisappear. Udało mi się zobaczyć ukrywanie paska stanu za pomocą animacji .Slide, ale ponieważ pasek stanu był niewidoczny po wybraniu katalogu, nie byłem w stanie wyświetlić paska stanu. Ponownie, zielona bateria wróciła, a reszta paska stanu była niewidoczna po zamknięciu kontrolera widoku modalnego. Próbowałem również przesłonić prefersStatusBarHidden (), ale ta funkcja nigdy nie została wywołana, więc próbowałem wywołać metodę setNeedsStatusBarAppearanceUpdate (), aby upewnić się, że system wywołuje metodę prefersStatusBarHidden (), ale nadal nie jest wywoływana. Również, istnieje sugestia, aby ustawić pasek stanu tak, aby był ukryty w metodzie delegata navigationController willShowViewController. Po raz kolejny wszystko to powoduje ukrycie paska stanu, co nie rozwiązuje problemu. Jak się okazuje, wydaje się, że styl paska stanu zmienia się po umieszczeniu na stosie nawigacyjnym UIImagePickerController. Aby całkowicie rozwiązać problem, nie musiałem pisać rozszerzeń ani podklasy UIImagePickerController. Wszystko, co musisz zrobić, to ustawić delegata i ustawić styl paska stanu na ten sam. Ten dodatek sprawił, że problem nigdy nie istniał. wydaje się, że styl paska stanu jest zmieniany po umieszczeniu na stosie nawigacyjnym UIImagePickerController. Aby całkowicie rozwiązać problem, nie musiałem pisać rozszerzeń ani podklasy UIImagePickerController. Wszystko, co musisz zrobić, to ustawić delegata i ustawić styl paska stanu na ten sam. Ten dodatek sprawił, że problem nigdy nie istniał. wydaje się, że styl paska stanu jest zmieniany po umieszczeniu na stosie nawigacyjnym UIImagePickerController. Aby całkowicie rozwiązać problem, nie musiałem pisać rozszerzeń ani podklasy UIImagePickerController. Wszystko, co musisz zrobić, to ustawić delegata i ustawić styl paska stanu na ten sam. Ten dodatek sprawił, że problem nigdy nie istniał.

let pickerController = UIImagePickerController()
pickerController.delegate = self

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
        UIApplication.sharedApplication().setStatusBarStyle(.LightContent, animated: false)
    }
SwiftMatt
źródło
-1

Właściwie znalazłem lepszy sposób na ustawienie koloru tła paska stanu w Próbniku obrazów. Zasadniczo musisz ustawić backgroundImage z NavigationBar na nil, ponieważ domyślnie w selektorze obrazów ma backgroundImage jako biały obraz.

André Luiz Alves
źródło