30 votes

Comment contraindre l'autorotation à une seule orientation pour certaines vues, tout en autorisant toutes les orientations sur d'autres?

Cette question est à propos de l'appareil iOS rotation et de multiples contrôlés points de vue dans un UINavigationController. Certains points de vue devraient être contraint de portrait de l'orientation, et certains devraient autorotate librement. Si vous essayez de créer la configuration la plus simple, avec trois points de vue, vous remarquerez que l'autorotation comportement a quelques très méchant bizarreries. Le scénario est, cependant, très simple, donc je pense que je vais pas faire l'autorotation mise en œuvre correctement, ou j'oublie quelque chose.

J'ai une base de démonstration app qui montre l'étrangeté, et j'ai fait une vidéo le montrant en action.

L'installation est très simple: Trois voir les contrôleurs appelés FirstViewController, SecondViewController et ThirdViewController tous étendre AbstractViewController qui montre une étiquette avec le nom et que le retour OUI pour shouldAutorotateToInterfaceOrientation: lorsque l'appareil est en orientation portrait. Le SecondViewController remplace la cette méthode pour permettre à tous les rotations. Tous les trois classes de béton ajouter quelques carrés de couleur pour être en mesure de naviguer entre les points de vue, en poussant et en sautant les contrôleurs sur/off de l' UINavigationController. Jusqu'à présent, un scénario très simple, je dirais.

Si vous tenez l'appareil en mode portrait ou paysage, c'est le résultat que je ne souhaite pas uniquement à réaliser, mais il serait également s'attendre. Dans la première image que vous voyez que tous les points de vue sont "debout", et dans le deuxième vous voyez que seul le second point de vue contrôleur de contre-fait pivoter l'appareil de l'orientation. Pour être clair, il devrait être possible de naviguer à partir de la seconde vue en mode paysage pour la troisième, mais parce que le troisième prend uniquement en charge le mode portrait, il ne doit être indiqué dans l'orientation portrait. La meilleure façon de voir si les résultats sont bon, c'est en regardant la position du transporteur bar.

Expected view orientation for the device in portrait modeExpected view orientation for the device in landscape mode

Mais cette question ici, car le résultat est complètement différent. Selon ce point de vue, vous êtes lorsque vous faites pivoter l'appareil, et selon ce point de vue, vous accédez à la prochaine, les points de vue ne tourne pas (pour être précis, l' didOrientFromInterfaceOrientation: méthode n'est jamais appelé). Si vous êtes en mode paysage sur le deuxième et accédez à la troisième, elle a la même orientation que la seconde (=mauvais). Si vous naviguez à partir de la deuxième retour à la première toutefois, l'écran va tourner dans un "forcé" en mode portrait, et le transporteur bar sera à la physique dessus de l'appareil, indépendamment de la façon dont vous êtes titulaire d'elle. La vidéo montre plus en détail.

Actual view orientation for the device in landscape mode

Ma question est double:

  1. Pourquoi le premier point de vue contrôleur de tourner en arrière, mais pas le troisième?
  2. Ce qui doit être fait pour obtenir le bon comportement de votre point de vue quand vous voulez seulement quelques points de vue à rotation automatique, mais pas d'autres?

Cheers, EP.

EDIT: Comme un dernier recours avant de mettre un bounty sur elle, j'ai complètement réécrit cette question pour être plus court, plus clair et j'espère que plus d'invitation à donner une réponse.

8voto

A. R. Younce Points 709

La réponse courte est que vous êtes en utilisant un UINavigationController, et qui ne fonctionnent pas comme vous le souhaitez. À partir d'Apple docs:

Pourquoi ne pas en faire mon UIViewController tourner avec l'appareil?

Tout enfant de voir les contrôleurs de UITabBarController ou UINavigationController ne sont pas d'accord sur une orientation commune ensemble.

Assurez-vous que tous vos enfants de vue les contrôleurs de tourner correctement, vous devez mettre en œuvre shouldAutorotateToInterfaceOrientation pour chaque vue, contrôleur de représentant chaque onglet de navigation ou de niveau. Chaque doivent s'entendre sur la même orientation pour qui tournent à se produire. C'est qu'ils tout devrait rentrer OUI pour les mêmes l'orientation des positions.

Vous pouvez en lire plus à propos de rotation de la vue des questions ici.

Vous devrez supprimer votre propre point de vue/contrôleur de gestion de la pile pour ce que vous voulez faire.

5voto

Abo3atef Points 166

Faire un bolean dans délégué d'Application pour le contrôle de l'orientation qui vous voulez par exemple faire un bool pour activer le Portrait et dans votre vue-contrôleur que vous souhaitez autoriser Portrait de l'activer à l'application partagée

dans votre vue-contrôleur,où vous voulez activer ou désactiver ce que jamais orientation que vous voulez.

((APPNAMEAppDelegate *)[[UIApplication sharedApplication] delegate]).enablePortrait= NO;

en Application de Délégué.

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    NSLog(@"Interface orientations");
    if(!enablePortrait)
        return UIInterfaceOrientationMaskLandscape;
    return UIInterfaceOrientationMaskLandscape|UIInterfaceOrientationMaskPortrait;
}

Cette méthode sera déclenché à chaque fois que vous faites pivoter l'appareil, sur la Base de ces BOOL permettre l'orientation que vous voulez.

4voto

B_. Points 1009

Il y a une question similaire il y a quelques années avec un certain nombre de réponses. Voici une récente réponse de quelqu'un à cette question:
Est-il documenté pour régler l'iPhone de l'orientation?

D'après ce que je comprends, c'est un problème que beaucoup de gens ont et surtout les hacks sont le seul moyen pour résoudre ce problème. Regardez à travers ce thread si vous n'avez pas vu avant, et voir si tout fonctionne pour vous.

Sur une note de côté, j'ai eu un problème similaire pour un moment en arrière, lorsque j'ai été appeler quelque chose dans shouldAutorotate et j'ai ajouté un peu de code pour viewWillAppear pour essayer de le réparer. Honnêtement, je ne me souviens pas si cela a fonctionné et je n'ai pas de Mac plus pour l'essayer, mais j'ai trouvé le code et je vais le coller ici dans le cas où il donne toute inspiration.

- (void)viewWillAppear:(BOOL)animated{
  UIInterfaceOrientation o;
  switch ([UIDevice currentDevice].orientation) {
    case UIDeviceOrientationPortrait:
        o = UIInterfaceOrientationPortrait;
        break;
    case UIDeviceOrientationLandscapeLeft:
        o = UIInterfaceOrientationLandscapeLeft;
        break;
    case UIDeviceOrientationLandscapeRight:
        o = UIInterfaceOrientationLandscapeRight;
        break;
    default:
        break;
  }

  [self shouldAutorotateToInterfaceOrientation:o];
}

2voto

epologee Points 3812

NE PAS UTILISER CE HACK, APPLE VA REJETER L'APPLICATION BASÉE SUR L'UTILISATION PRIVÉE DE L'API"

Pour l'amour de la référence, je vais quitter ma réponse ici, mais l'utilisation privée de l'API ne glisse pas passé le conseil de révision. J'ai appris quelque chose aujourd'hui :D Comme @younce cité de la Pomme docs correctement, ce que je veux, ne peut être réalisé avec la UINavigationController.

J'avais deux options. Tout d'abord, je pourrais avoir écrit mon propre manette de navigation de substitution, avec toutes les horreurs que l'on aurait rencontré tout en le faisant. Deuxièmement, j'ai pu avoir piraté la rotation de la vue des contrôleurs, à l'aide d'une fonction non documentée de UIDevice appelés setOrientation:animated:

Parce que le deuxième était tentante facile, je suis allé pour cela. C'est ce que j'ai fait. Vous aurez besoin d'une catégorie à supprimer les avertissements du compilateur sur le setter n'existant pas:

@interface UIDevice (UndocumentedFeatures) 
-(void)setOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated;
-(void)setOrientation:(UIInterfaceOrientation)orientation;
@end

Ensuite, vous devez vérifier pour la pris en charge des orientations sur viewWillAppear:. À côté de la UIDevice méthodes utilisées ici, vous pouvez également forcer l'orientation portrait, par la présentation d'un modal-vue-contrôleur, mais qui va se passer instantanément et pas d'animation, c'est ma manière préférée:

-(void)viewWillAppear:(BOOL)animated {
    UIDevice *device = [UIDevice currentDevice];
    UIDeviceOrientation realOrientation = device.orientation;

    if ([self shouldAutorotateToInterfaceOrientation:realOrientation]) {
        if (realOrientation != [UIApplication sharedApplication].statusBarOrientation) {

            // Resetting the orientation will trigger the application to rotate
            if ([device respondsToSelector:@selector(setOrientation:animated:)]) {
                [device setOrientation:realOrientation animated:animated];
            } else {
                // Yes if Apple changes the implementation of this undocumented setter,
                // we're back to square one.
            }
        }
    } else if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) {
        if ([device respondsToSelector:@selector(setOrientation:animated:)]) {

            // Then set the desired orientation
            [device setOrientation:UIDeviceOrientationPortrait animated:animated];

            // And set the real orientation back, we don't want to truly mess with the iPhone's balance system.
            // Because the view does not rotate on this orientation, it won't influence the app visually.
            [device setOrientation:realOrientation animated:animated];
        }
    }
}

L'astuce est de toujours garder l'intérieur de l'appareil orientation de la 'vraie' orientation de l'appareil. Si vous commencez à changer, la rotation de votre application sera hors de l'équilibre.

Mais comme je le sais maintenant, c'est juste un moyen sûr d'obtenir votre application rejeté. Si l'option numéro deux, c'est juste une mauvaise option. Réécriture NavigationController, ou tout simplement avoir tous vos points de vue du soutien à l'orientation définie.

Cheers, EP.

2voto

AMayes Points 1101

Dans iOS 6, cela est devenu un problème très simple. Créez simplement une classe spéciale pour les vues que vous souhaitez autoroter. Ensuite, dans votre rootVC, ajoutez ceci.

 -(BOOL)shouldAutorotate{
       BOOL should = NO;

       NSLog(@"%@", [self.viewControllers[self.viewControllers.count-1] class]);
       if ([self.viewControllers[self.viewControllers.count-1] isKindOfClass:[YourAutorotatingClass class]]) {
             should = YES;
       }


       return should;
}
 

Je sais que c'est une vieille question, mais j'ai pensé qu'il valait la peine d'être mentionné.

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