Empêche la barre d'état iOS en cours d'appel de pousser Phonegap UIWebView hors écran

Mon problème est le suivant: chaque fois qu'un user de l'iPhone est en appel, ou utilise son téléphone comme un hotspot, la barre d'état d'iOS 7 est agrandie, poussant ainsi l'UIWebView de mon application Phonegap au bas de l'écran. La barre d'état agrandie est appelée "barre d'état en cours d'appel". Voir ci-dessous l'image:

Wonky barre d'état en cours d'appel.

Stack Overflow réponses J'ai essayé d'y remédier:

Iphone- Comment resize la vue lorsque la barre d'état de l'appel est basculée?

Comment la barre d'état en appel affecte la taille de vue de UIViewController? (et comment le gérer correctement)

De plus, il ne semble pas y avoir d'événement déclenché par Phonegap qui m'informe du changement de la barre d'état. L'écoute de l'événement "pause" de Phonegap est inutile, car 1) il est connu pour avoir des bizarreries dans iOS et 2) il ne couvre pas vraiment le cas du hotspot.

Mes compétences en Objective-C sont très minimes, et je n'ai recours à ce type de question qu'après avoir mis en place les 4 heures et plus nécessaires pour googler, emstackr, déborder, hurler, etc …

Dieux de l'emstackment Débordement, rends-moi ta furie de nerd généreuse.

Je suis venu avec la solution suivante basée sur les suggestions de Jef. Ce que vous voulez faire est le suivant:

  • Observez le délégué natif didChangeStatusBarFrame
  • Obtenez des informations sur la taille de la barre d'état via le statusBarFrame
  • Exposez des informations à votre webview en déclenchant un événement qui le passe

J'ai mis en place un repo Github avec tout le code que vous trouvez dans cette réponse.

Notification d'installation dans AppDelegate

 // Appdelegate.m - (void)application:(UIApplication *)application didChangeStatusBarFrame:(CGRect)oldStatusBarFrame { NSMutableDictionary *statusBarChangeInfo = [[NSMutableDictionary alloc] init]; [statusBarChangeInfo setObject:@"statusbarchange" forKey:@"frame"]; [[NSNotificationCenter defaultCenter] postNotificationName:@"statusbarchange" object:self userInfo:statusBarChangeInfo]; } 

Rendre le sélecteur statusBarChange disponible

 // MainViewController.h @protocol StatusBarChange <NSObject> -(void)onStatusbarChange:(NSNotification*)notification; @end 

Configurez l'écouteur. Cela obtient les dictionarys d' origin et de size de statusBarFrame chaque fois qu'il change et triggers un événement dans le webview qui passe le long de ces données.

 // MainViewController.m - (void)onStatusbarChange:(NSNotification*)notification { // Native code for NSMutableDictionary *eventInfo = [self getStatusBarInfo]; [self notifiy:notification.name withInfo:eventInfo]; } - (void)notifiy:(NSSsortingng*)event withInfo:(NSMutableDictionary*)info { NSSsortingng *json = [self toJSON:info]; NSSsortingng *cmd = [NSSsortingng ssortingngWithFormat:@"cordova.fireWindowEvent('\%@\', %@)", event, json]; [self.webView ssortingngByEvaluatingJavaScriptFromSsortingng:cmd]; } - (NSMutableDictionary *)getStatusBarInfo { CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame]; NSMutableDictionary *statusBarInfo = [[NSMutableDictionary alloc] init]; NSMutableDictionary *size = [[NSMutableDictionary alloc] init]; NSMutableDictionary *origin = [[NSMutableDictionary alloc] init]; size[@"height"] = [NSNumber numberWithInteger:((int) statusBarFrame.size.height)]; size[@"width"] = [NSNumber numberWithInteger:((int) statusBarFrame.size.width)]; origin[@"x"] = [NSNumber numberWithInteger:((int) statusBarFrame.origin.x)]; origin[@"y"] = [NSNumber numberWithInteger:((int) statusBarFrame.origin.y)]; statusBarInfo[@"size"] = size; statusBarInfo[@"origin"] = origin; return statusBarInfo; } - (NSSsortingng *) toJSON:(NSDictionary *)dictionary { NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error]; return [[NSSsortingng alloc] initWithData:jsonData encoding:NSUTF8SsortingngEncoding]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } 

Tout cela vous permet d'écouter l'événement window.statusbarchange , par exemple:

 // www/js/index.js window.addEventListener('statusbarchange', function(e){ // Use e.size.height to adapt to the changing status bar }, false) 

Je dirais que ça arrive toujours quand tu rentres de l'arrière-plan, non?

Dans d'autres mots, est-il possible que la barre s'agrandisse sans que votre application soit au less brièvement mise à l'arrière-plan par un appel entrant, etc.?

Si oui, vous pouvez interroger la hauteur de la barre d'état dans vos delegates – (void) will (orDid) reprendra et ajuster en conséquence?

Si cela arrive sans que l'avant-plan soit rendu un peu plus difficile, nous devrons déterminer les notifications à observer, je sais qu'il y a une interruption audioSession notif dans le cas des appels entrants, pas sûr de l'hotspot mais sûrement il y a une notification pour ça aussi ..

Modifier ok ici ils sont, choisissez l'une de ces notifications à observer ..

 UIApplicationWillChangeStatusBarFrameNotification UIApplicationDidChangeStatusBarFrameNotification 

Ou implémentez l'un de ces callbacks dans votre délégué

 -application:willChangeStatusBarFrame: -application:didChangeStatusBarFrame: