J'ai donc cette application iPhone avec une installation imbriquée comme ceci: [RootViewController] -> [UITabBarController] -> [UINavigationController] -> [subViewControllers]. Tout est construit par programme, pas dans Interface Builder. J'essaye simplement de supporter toutes les orientations de l'appareil. Tous mes masques AutoResizing sont configurés et tout tourne et se développe/se contracte si nécessaire. Tout sauf le navBar et la barre d'outils du NavigationController. (Normalement, ces vues sont automatiquement redimensionnées automatiquement en fonction de l'orientation, par exemple en mode paysage, la barre de navigation et la barre d'outils doivent automatiquement être redimensionnées à environ 32px et 44px en mode Portrai.) La sous-vue du contrôleur de navigation est redimensionnée le navBar et la barre d'outils ne le sont pas. En d'autres termes, le contenu s'étire/se rétracte environ 12 px ou plus dans n'importe quelle direction comme si la barre de navigation et la barre d'outils étaient redimensionnées. Cela semble être les masques autoresizing faisant leur travail.UINavigationController Barre d'outils et orientation du périphérique (rotation)
Donc, pour tenter de résoudre cette situation, j'ai créé une catégorie pour UINavigationController qui répond à 'willRotateToInterfaceOrientation: duration:' afin de déclencher le sélecteur 'sizeToFit'. (Cette technique provenait d'un autre post sur Stack Overflow, avec un problème similaire.) J'ai découvert, dans mes recherches, que seul le contrôleur de vue le plus externe recevait ce message, mon contrôleur de vue racine l'appelle donc sur le contrôleur de tabulation, à son tour l'appelle sur le contrôleur de navigation, etc. Cela a pris soin de ce problème, et maintenant mes contrôleurs de vue imbriqués sont notifiés lorsque la vue extérieure est tournée. À l'aide de la technique sizeToFit, la barre de navigation et la barre d'outils se redimensionnent toutes seules. Cependant, cela laisse toujours le problème du repositionnement de la barre d'outils, afin de compenser le décalage par rapport au changement de taille. (Puisque nos coordonnées de vue dans iPhone commencent en haut à gauche.)
Ce qui rend cette tâche difficile à faire dans la méthode willRotate, c'est que nous n'avons aucun moyen de savoir quelles seront les nouvelles dimensions de la vue englobante, et nous ne savons pas non plus quoi faire. notre orientation actuelle est. (À moins que deviceOrientationNotifications ne soit activé, ce que je ne fais pas.) Tout ce que nous devons travailler, c'est ce que sera la nouvelle orientation, et quelles sont les valeurs d'images actuelles de notre barre d'outils. Je pourrais le coder en dur et calculer les ajustements de cadre à l'ancienne en utilisant un morceau de papier brouillon, mais je veux vraiment conserver les fonctions de dimensionnement de la vue dynamique sans faire de suppositions sur les dimensions de l'écran de l'appareil. Par conséquent, en utilisant le code suivant, j'ai réussi à remédier à cela en "bousculant" la barre d'outils de 12px par rapport à la taille qu'elle vient de devenir. Pour éviter que l'utilisateur ne fasse trop de bruit lorsque l'utilisateur bascule l'appareil, j'utilise la hauteur du cadre de la barre d'outils actuelle pour dériver l'orientation actuelle. (Cela signifie que je fais encore une hypothèse concernant avant et après les tailles de la barre d'outils, mais je me sens mieux depuis que je peux influencer ce à un degré plutôt que d'essayer de redimensionner programme écran physique de l'appareil.)
@implementation UINavigationController (BLUINavigationControllerAutoRotate)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return TRUE;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Resize the navBar
[[self navigationBar] performSelector:@selector(sizeToFit)
withObject:nil
afterDelay:(0.5f * duration)];
// Read our current frame size
CGRect toolbarFrame = self.toolbar.frame;
// Prevent over adjusting when flipping the device
if ((toolbarFrame.size.height < 38
&& (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft
|| toInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
|| (toolbarFrame.size.height > 38
&& (toInterfaceOrientation == UIInterfaceOrientationPortrait
|| toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)))
{
// We are already resized and repositioned.
return;
}
// Calculate and apply the toolbar offset
const NSInteger delta = 12; // the difference in size between 44 and 32 px.
toolbarFrame.origin.y += ((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft)
|| (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)) ? (delta) : (-delta);
self.toolbar.frame = toolbarFrame;
// Resize the toolbar
[[self toolbar] performSelector:@selector(sizeToFit)
withObject:nil
afterDelay:(0.5f * duration)];
}
@end
Donc, maintenant j'ai correctement comporté NavigationBar et barre d'outils. L'utilisateur final ne saura jamais que j'ai dû mettre en œuvre tout ce travail supplémentaire afin de réactiver ce qui semble être un comportement standard. Donc ma question est, pourquoi dois-je faire tout cela? Y a-t-il une meilleure approche que je devrais connaître, ou quelque chose que je ne fais tout simplement pas ailleurs? (c'est-à-dire [navigationController setAutomaticallyResizesToolbarOnRotate: TRUE], ou quelque chose comme ça?) Comme je l'ai dit, cela semble être supposé être pré-câblé, donc pour moi de devoir transférer des messages et des déclencheurs forcés plutôt que la bonne solution.
Merci!
Oui! Ça marche. En fait, il suffit d'ajouter 'willAnimateRotationToInterfaceOrientation:' pour le faire fonctionner. J'ai déjà eu willRotate et didRotate. Cependant, si vous utilisez 'willAnimateRotationToInterfaceOrientation:' vous ne devez pas utiliser 'willAnimateFirstHalfOfRotationToInterfaceOrientation: ou' willAnimateSecondHalfOfRotationToInterfaceOrientation '. Il en va de même pour les méthodes 'didAnimate ...'. Quoi qu'il en soit, long histoire courte, (littéralement) c'est tout ce qu'il faut. Merci! :) – quickthyme