35 votes

Manière la plus facile de prendre en charge plusieurs orientations? Comment puis-je charger un personnalisé PLUME lorsque l'application est en mode Paysage?

J'ai une application dans laquelle je tiens à soutenir plusieurs orientations. J'en ai deux .xib les fichiers que je veux utiliser, myViewController.xib et myViewControllerLandscape.xib. myViewController.xib existe dans un projet/Ressources et de l' myViewControllerLandscape.xib existe à la racine du répertoire du projet.

Ce que je veux faire est d'utiliser une PLUME (myViewControllerLandscape.xib) de mes rotations. J'essaie de détection de rotation en viewDidLoad like ceci:

if((self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight))
 {
  NSLog(@"Landscape detected!");
  [self initWithNibName:@"myViewControllerLandscape" bundle:nil];

 }

Mais je peux voir dans gdb que ce n'est pas exécutée lorsque l'application est démarrée avec l'appareil en mode paysage. Le NSLog message n'est pas le feu. Pourquoi est-ce? Qu'ai-je fait de mal?

Aussi, si j'ai choisi de mettre l' initWithNibName appel de fonction dans l' viewDidLoad méthode, que la plume n'est pas chargé, et elle se poursuit avec le myViewController.xib fichier. Quel est le problème avec mon appel? Dois-je spécifier un bundle?

Merci!

59voto

Adam Points 17726

J'ai trouvé une bien meilleure manière qui fonctionne indépendamment de la valeur liquidative du contrôleur. Maintenant, j'ai ce travail lorsqu'il est incorporé dans un nav contrôleur, et NON incorporés (bien que je ne suis pas en utilisant la valeur liquidative du contrôleur pour l'instant, alors il peut y avoir quelques bug, je ne l'ai pas vu - par exemple, la POUSSÉE animation de transition pourrait aller drôle, ou quelque chose)

Deux Plumes, à l'aide d'Apple convention de nommage. Je soupçonne que dans iOS 6 ou 7, Apple pourrait ajouter à cela comme une "fonction". Je l'utilise dans mes applications et il fonctionne parfaitement:

  1. déclencheurs qui VA tourner, ne DOIT tourner (attend jusqu'à ce que la rotation de l'anim est sur le point de commencer)
  2. utilise la Pomme convention de nommage pour portrait/paysage fichiers (par Défaut.png est par Défaut-paysage.png si vous voulez Apple pour charger automatiquement une version paysage)
  3. la recharge de la nouvelle PLUME
  4. ce qui réinitialise l' self.view - ce qui va AUTOMATIQUEMENT mettre à jour l'affichage
  5. puis il appelle viewDidLoad (Apple ne sera PAS appeler pour vous, si vous avez manuellement recharger une PLUME)
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation) )
    {
        [[NSBundle mainBundle] loadNibNamed: [NSString stringWithFormat:@"%@-landscape", NSStringFromClass([self class])]
                                      owner: self
                                    options: nil];
        [self viewDidLoad];
    }
    else
    {
        [[NSBundle mainBundle] loadNibNamed: [NSString stringWithFormat:@"%@", NSStringFromClass([self class])]
                                      owner: self
                                    options: nil];
        [self viewDidLoad];
    }
}

40voto

TechZen Points 52692

Vous avez à charge un point de vue, puis vérifiez l'orientation et de charger une autre si besoin. Vous vérifiez l'orientation en shouldAutorotateToInterfaceOrientation: retour oui si vous souhaitez faire pivoter.

J'utilise une manette de navigation pour gérer la transition. Si j'ai le portrait de la vue et de l'appareil tourne, je pousse le paysage de la vue et de la pop à la mode paysage quand il retour à portrait.

Edit:

Je retourne OUI pour toutes les orientations dans shouldAutorotateToInterfaceOrientation: mais cela sera appelée lors de l'application lance? Ne vous poussez votre point de vue à l'intérieur de de cette fonction?

L'orientation des constantes ne sont pas globals vous interrogez mais plutôt une partie des messages envoyés au contrôleur par le système. En tant que tel, vous ne pouvez pas facilement détecter l'orientation avant de une-vue-contrôleur de charge. Au lieu de cela, vous pouvez brancher l'application de se lancer dans une orientation particulière (généralement portrait), puis immédiatement à tourner. (Voir le navigateur Safari mobile. Il démarre toujours en mode portrait et tourne ensuite vers le paysage.)

Ce sont les deux méthodes que j'utilise pour échanger mes vues portrait et paysage.

Tous les trois vue dans les contrôleurs de cette méthode:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

Le portrait a ceci:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

    if (toInterfaceOrientation==UIInterfaceOrientationLandscapeRight) {
        [self.nav pushViewController:rightLVC animated:NO];
    }
    if (toInterfaceOrientation==UIInterfaceOrientationLandscapeLeft) {
        [self.nav pushViewController:leftLVC animated:NO];
    }
}

Chaque paysage contrôleur a ceci:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

    if (toInterfaceOrientation==UIInterfaceOrientationPortrait) {
        [self.nav popViewControllerAnimated:NO];
    }

L'application démarre en mode portrait. Si l'orientation de l'appareil est paysage, il pousse le approprié paysages. Lorsque l'appareil tourne le dos au portrait, il apparaît le paysage. Pour l'utilisateur, il ressemble à la même vue de la réorganisation de lui-même pour une autre orientation.

5voto

amergin Points 960

Vraiment comme Adam réponse - je l'ai modifiée légèrement pour permettre le chargement initial de la plume en portrait ou paysage

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    if( !nibNameOrNil )     nibNameOrNil = [self nibNameRotated:[[UIApplication sharedApplication] statusBarOrientation]];
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    return self;
}

- (NSString*) nibNameRotated:(UIInterfaceOrientation)orientation
{
    if( UIInterfaceOrientationIsLandscape(orientation))     return [NSString stringWithFormat:@"%@-landscape", NSStringFromClass([self class])];
    return [NSString stringWithFormat:@"%@", NSStringFromClass([self class])];
}

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    NSString *nibname = [self nibNameRotated:toInterfaceOrientation];
    [[NSBundle mainBundle] loadNibNamed:nibname owner:self options:nil];
    [self viewDidLoad];
}

1voto

David Gelbart Points 152

J'aime TechZen accepté de répondre, mais comme le souligne Adam commentaire, il quitte le portrait-vue-contrôleur dans la pile de navigation lorsque vous faites pivoter en mode paysage. Cela signifie appuyant sur le bouton retour dans la barre de navigation, tandis que, dans le paysage, l'utilisateur sera en orientation portrait. Un collègue de travail et j'essaie l'approche de supprimer manuellement l'élément supplémentaire de la valeur liquidative de la pile. Il semble fonctionner mais j'ai très peu d'expérience encore, donc je fais pas de promesses. Voici un exemple de code:

Pour passer de portrait à paysage:

[[self navigationController] pushViewController:landscapeViewController animated:NO];
[self removeFromNavigationStack:[MyPortraitViewController class]];

Pour revenir à portrait:

[[self navigationController] pushViewController:portraitViewController animated:NO];
[self removeFromNavigationStack:[MyLandscapeViewController class]];

Si vous n'utilisez pas d'animation:NON, vous pouvez obtenir des avertissements concernant l'état de la navigation.

Helper:

- (void)removeFromNavigationStack:(Class)oldClass {
      UINavigationController *nav = [self navigationController];
      NSMutableArray *newStack = [NSMutableArray array];
      for (UIViewController *vc in nav.viewControllers) {
          if (![vc isMemberOfClass:[oldClass class]]) {
              [newStack addObject: vc];            
          }
      [nav setViewControllers:newStack animated:NO];
  }

1voto

ohho Points 17243

Un choix de plus, TPMultiLayoutViewController.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X