UIPopoverController redimensionnant automatiquement à la hauteur maximale sur pushViewController

J’ai un popover contenant un UINavigationController. Je peux très bien afficher le popover et il contient très bien le navController. Le navController contient une tableView et lorsque je sélectionne un élément, il crée une nouvelle vue détaillée:

DeviceDetailViewController *detailViewController = [[[DeviceDetailViewController alloc] initWithNibName:@"DeviceDetailViewController" bundle:nil] autorelease]; 

Je pousse alors le nouveau contrôleur de vue:

  [self.navigationController pushViewController:detailViewController animated:YES]; 

C’est à ce moment que le problème survient: après avoir appuyé sur la nouvelle vue, le popover est redimensionné à la hauteur maximale disponible sur l’iPad.

J’ai essayé de régler la hauteur de toutes les vues dans le xib à une hauteur fixe plutôt que flexible. J’ai essayé de définir explicitement la hauteur du popover. J’ai également essayé d’utiliser différents contrôleurs de vue comme vue enfant. Le problème persiste: le popover souhaite se redimensionner automatiquement à la hauteur maximale chaque fois qu’une nouvelle vue est transmise au contrôleur de navigation.

Voici une question qui traite de la tentative de contrôler délibérément la taille du popover en poussant de nouvelles vues:

Je pensais que cela pourrait être une méthode de force brute pour contrôler la taille. Assez étrangement, cependant, cela provoque des bizarreries graphiques rapides (comme si la vue était fraîchement animée) suivie par la poursuite du redimensionnement comme décrit ci-dessus.

En d’autres termes, quelque chose force littéralement le popover à sa hauteur maximale, et il semble se produire après l’ appel de toutes les méthodes de délégation.

Est-ce le contrôleur de navigation? Quelqu’un a-t-il vu ce genre de chose?

Cela corrigé pour moi après avoir eu le même problème (par coïncidence aussi aujourd’hui):

EDIT : comme contentSizeForViewInPopover est obsolète dans iOS7.0 , utilisez preferredContentSize .

Réponse originale cidessous :

Dans votre detailViewController ajoutez ceci:

 - (void)viewWillAppear:(BOOL)animated { CGSize size = CGSizeMake(320, 480); // size of view in popover self.contentSizeForViewInPopover = size; [super viewWillAppear:animated]; } 

Vous souhaitez également append quelque chose de similaire à votre DeviceDetailViewController d’origine pour empêcher le redimensionnement lors de l’utilisation de NavbarItem arrière.

Tout comme le gérer dans viewWillAppear , une autre façon de gérer cela consiste à remplacer contentSizeForViewInPopover . Très laconique:

 -(CGSize)contentSizeForViewInPopover { return self.view.bounds.size; } 

Pour IOS5

Je vous recommande de le faire en:

 - (void)viewDidLoad { [super viewDidLoad]; CGSize size = CGSizeMake(320, 480); // size of view in popover self.contentSizeForViewInPopover = size; } 

J’ai eu un problème similaire.

J’ai eu un popover présent à partir d’un bouton dans une barre d’outils. Le popover était défini sur une taille spécifique. C’était une vue de table. Lorsque la ligne du tableau a été sélectionnée, un nouveau contrôleur de vue avec un contrôleur de navigation a été appelé.

Lorsque le bouton Retour a été sélectionné, le popover est devenu la taille par défaut (320×1100, je crois), au lieu de la taille spécifique souhaitée.

Le code d’origine était:

  MyTableViewController *myVC = [[MyTableViewController alloc] init]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC]; UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController]; popover.delegate = self; popover.popoverContentSize = CGSizeMake(400.0, 500.0); [myVC release]; [navController release]; [popover release]; 

J’ai ajouté une ligne pour résoudre le problème. Certes, c’est un peu un travail de contournement parce que je devais soustraire la hauteur de l’en-tête. Peut-être l’un d’entre vous pourrait-il m’éclairer avec une meilleure méthode. En tout cas, ça marche.

  MyTableViewController *myVC = [[MyTableViewController alloc] init]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myVC]; UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController]; popover.delegate = self; popover.popoverContentSize = CGSizeMake(400.0, 500.0); //Subtract the height of the header to match the total popover size (not just the view). myVC.contentSizeForViewInPopover = CGSizeMake(400.0, 500-44); [myVC release]; [navController release]; [popover release]; 

Je pense que lorsqu’un contrôleur de navigation est impliqué et que le bouton Retour est enfoncé, la taille par défaut du pop-up est définie par défaut. En ajoutant la propriété contentSizeForViewInPopover pour le contrôleur de vue myVC, il force la taille spécifique.

J’espère que c’est utile.

Kurt

Pour iOS 7, utilisez ce qui suit:

 - (void)viewDidLoad { [super viewDidLoad]; CGSize size = CGSizeMake(320, 768); // size of view in popover self.preferredContentSize = size; } 

UIViewController.contentSizeForViewInPopover est devenu obsolète dans iOS 7.

En réponse à des problèmes graphiques avec des animations:

Les animations UIPopoverController entrent en conflit avec les animations des contrôleurs UINavigation, si vous créez le popover avec un UINavigationController à l’intérieur. Il en résulte des problèmes graphiques lors de l’animation. Pour résoudre le problème, définissez le paramètre animé sur false lorsque vous appuyez sur d’autres contrôleurs ou lorsque vous affichez la barre d’outils.

Contrôleurs de vue poussante:

 [self.navigationController pushViewController:detailViewController animated:NO]; 

Rendre la barre d’outils visible:

 [[self navigationController] setToolbarHidden:NO animated:NO]; 

Paramétrer l’animation: NO fera en sorte que les animations semblent correctes dans un UIPopoverController.

Pourquoi ne pas simplement définir contentSizeForViewInPopover avant de pousser le contrôleur suivant sur la stack de navigation? Pas besoin de définir des tailles dans viewWillAppear et autres.

 [nextController setContentSizeForViewInPopover:[self contentSizeForViewInPopover]]; [[self navigationController] pushViewController:nextController animated:YES]; 

Fonctionne sur IOS 5.1

Légère variante sur les conseils de borked (ce qui m’a orienté dans la bonne direction, merci pour ça!), Voici ce que je fais quand on pousse un nouveau contrôleur pour maintenir la taille avant de le pousser:

 productViewController.contentSizeForViewInPopover = self.view.bounds.size; self.contentSizeForViewInPopover = self.view.bounds.size; [self.navigationController pushViewController:productViewController animated:YES]; 

J’aime cela parce que je n’ai pas besoin de coder en dur les valeurs de popover dans chaque contrôleur de vue (bon puisque je les utilise à différentes hauteurs).

La ligne self.contentSizeForViewInPopover est destinée à préserver la taille lors du retour de l’utilisateur. Je suppose que vous pourriez mettre cette ligne ailleurs, comme viewWillAppear ou où vous voulez.

Semble travailler …

Dans le – (void) viewDidLoad de tous les contrôleurs de vue que vous utilisez en navigation, écrivez le code:

 self setContentSizeForViewInPopover:CGSizeMake(320, 500)]; 

Il existe deux manières de définir contentSizeForViewInPopover dans le storyboard. Vous pouvez définir vos contrôleurs de vue qui sont avec votre contrôleur de navigation sur FreeForm et définir les vues racine à la taille souhaitée. Ou, vous pouvez garder la mesure simulée comme déduite et cochez “Utiliser une taille explicite” et définissez la taille souhaitée.

Ensuite, dans chaque contrôleur de vue qui se trouve dans votre contrôleur de navigation, ajoutez les éléments suivants …

 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; ["yourpopoverController" setPopoverContentSize:CGSizeMake(self. contentSizeForViewInPopover.width, seld.contentSizeForViewInPopover.height + self. navigationController.navigationBar.frame.size.height) animated:YES]; } 

Dans l’animation de transition, la nouvelle vue s’alignera sur le haut et la hauteur sera ajustée en conséquence.

De cette façon, vous n’avez pas besoin de remplacer contentSizeForViewInPopover ou de spécifier une autre taille spécifiquement dans vos contrôleurs de vue. Tout est dans le storyboard.

Si l’un de vos contrôleurs de vue a une hauteur variable, vous devez remplacer contentSizeForViewInPopover dans cette vue, donc …

 - (CGSize)contentSizeForViewInPopover { return CGSizeMake(450, "calculate your height here"); } 

Ce truc peut avoir fonctionné une fois mais pas avec xCode 6 où contentSizeForViewInPopover est obsolète. Heureusement, il est respecté lors du chargement du storyboard. J’ai téléchargé un éditeur xml (Xmplify) et piraté le storyboard. Définissez la clé contentSizeForViewInPopover sur la taille souhaitée. Enregistrez et remplacez (créez d’abord une copie).

Plus précisement :

 < viewController>   

Ne travaille pas pour moi, quand j’utilise ceci:

 [UIPopoverController [UINavigationController] = root vc = [UIViewController vc1] => [UIViewController vc2] ] 

Lorsque apparait popover est tout bon, appuyez sur le bouton vc1 et appuyez sur vc2 vers le contrôleur de navigation

Revenez ensuite à vc1 (root) en appuyant sur le bouton dans vc2 (méthode popToRootViewController);

Nous pouvons voir que le popover change sa propre taille, mais la taille de vc1 est ancienne … QU’EST-CE QUE CE ???

Ok, maintenant le travail … Ajouter une propriété popover dans mon contrôleur

 self.contentSizeForViewInPopover = (CGSize){400, 200}; self.navigationController.contentSizeForViewInPopover = self.contentSizeForViewInPopover; self.popover.popoverContentSize = self.contentSizeForViewInPopover; 

En cours d’exécution Swift 4 et iOS 11, la seule solution possible était pour moi. Pour utiliser showViewController:sender: and showDetailViewController:sender: au lieu de presentViewController:animated:completion: showViewController:sender: and showDetailViewController:sender:

De l’Apple Doc

Les méthodes showViewController: sender: et showDetailViewController: sender: offrent le moyen le plus adaptable et le plus flexible d’afficher les contrôleurs de vue. Ces méthodes permettent au contrôleur de présentation de déterminer le meilleur moyen de gérer la présentation. Par exemple, un contrôleur de vue de conteneur peut incorporer le contrôleur de vue en tant qu’enfant au lieu de le présenter de manière modale. Le comportement par défaut présente le contrôleur de vue modalement.