Question

J'ai donc cette application iPhone avec une configuration imbriquée comme ceci: [RootViewController] -> [UITabBarController] -> [UINavigationController] -> [subViewControllers]. Tout est construit par programmation, pas dans Interface Builder.

Je suis tout simplement essayer de soutenir toutes les orientations de l'appareil. Tous mes masques Autoresizing sont mis en place et tout tourne et élargit la portée / contrats nécessaires. Tout sauf pour la barre de navigation et la barre d'outils du NavigationController. (Normalement, ces vues redimensionnement automatique automatiquement en fonction de l'orientation. Ie dans le paysage, la barre de navigation et la barre d'outils devrait redimensionner automatiquement à environ 32px et 44px en mode Portrai.) Ce qui est particulier est que la sous-vue du contrôleur de navigation est redimensionne, mais la barre de navigation réelle et barre d'outils ne sont pas. En d'autres termes, les étendues de contenu / psy environ 12 px ou si dans quelle direction comme si la barre de navigation et la barre d'outils redimensionnée. Cela semble être les masques de Autoresizing faire leur travail.

Ainsi, afin de tenter de résoudre cette situation, je créé une catégorie pour UINavigationController qui répond à « willRotateToInterfaceOrientation: durée: » afin de déclencher le sélecteur « sizeToFit ». (Cette technique est venue d'un autre poste sur le débordement de pile, avec un problème similaire.) J'ai découvert, dans mes recherches, que seul le contrôleur de vue externe reçoit ce message, cependant, j'ai donc mon contrôleur de vue racine appelez ce sur le contrôleur onglet, qui à son tour, il demande au contrôleur de navigation, etc. Cela a pris soin de ce problème, et maintenant mes contrôleurs de vue sont imbriqués être averti lorsque la vue extérieure est tournée. En utilisant la technique de sizeToFit, à la fois la barre de navigation et la barre d'outils redimensionnez eux-mêmes. Cependant, cela laisse encore la question du repositionnement de la barre d'outils, afin de compenser le décalage par rapport au changement de taille. (Étant donné que nos coordonnées en vue iPhone commencer en haut à gauche).

Ce qui rend ce difficile à faire dans la méthode willRotate, est que nous avons aucun moyen de savoir quelles sont les dimensions nouvelles de vue englobante seront, nous ne savons pas ce que notre orientation actuelle. (Sauf si vous avez deviceOrientationNotifications allumé, que je ne le fais pas.) Tout ce que nous devons travailler avec est ce que la nouvelle orientation sera, et quelles sont les valeurs de l'image en cours de notre barre d'outils sont. Je pourrais coder en dur cela et calculer les ajustements du cadre de la façon dont l'ancienne en utilisant un morceau de papier à gratter, mais je veux vraiment garder la vue dynamique caractéristiques de dimensionnement sans faire des hypothèses sur les dimensions de l'écran de l'appareil.

Par conséquent, en utilisant le code suivant, je réussis à y remédier par un simple «heurtant la barre d'outils par 12px par rapport à la taille, il est juste devenu. Pour l'empêcher de trop se cognant lorsque l'utilisateur bascule l'appareil, j'utilise la hauteur actuelle du cadre de barre d'outils pour obtenir l'orientation actuelle. (Cela signifie que je fais encore une hypothèse concernant de la barre d'outils avant et après la taille, 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

Alors, maintenant, je suis bien comporté NavigationBar et barre d'outils. L'utilisateur final ne saura jamais que je devais mettre en œuvre tout ce travail autour supplémentaire afin de réactiver ce qui semble être est censé être un comportement standard. Donc, ma question est, pourquoi dois-je faire tout cela? Y at-il une meilleure approche que je devrais savoir, ou quelque chose que je ne fais pas tout simplement ailleurs? (C.-à-[NavigationController setAutomaticallyResizesToolbarOnRotate: TRUE];? Ou quelque chose comme ça) Comme je l'ai dit, cela semble comme il est censé être pré-câblé, donc pour moi d'avoir finagle avec des messages et des déclencheurs forcés se sent expédition comme une bidouille sur-ingénierie plutôt que la solution appropriée.

Merci!

Était-ce utile?

La solution

Vous nous transmettons le message willRotateToInterfaceOrientation au contrôleur de vue de l'onglet de votre contrôleur de vue racine - pourquoi ne pas passer sur tous les autres messages de rotation et voir si cela aide? i.e..

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation  {
    [super didRotateFromInterfaceOrientation:toInterfaceOrientation];
    [tabBarController didRotateFromInterfaceOrientation:toInterfaceOrientation];
}

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    [super didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
    [tabBarController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
}

- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration];
}

Je serais curieux de voir ce qui se passe si vous passez tout cela à votre contrôleur de barre d'onglets - votre problème semble quelque chose qui devrait se faire automatiquement, au lieu d'être tout le travail supplémentaire que vous avez fait

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top