web-dev-qa-db-fra.com

Prise en charge d'une orientation différente pour une seule vue iOS 6

Je souhaite faire pivoter UNIQUEMENT l'une de mes vues dans mon application vers paysage à gauche ou paysage à droite. Toutes mes autres vues sont en mode portrait et j'ai configuré mon application pour prendre en charge uniquement le mode portrait. Avec l'orientation changée dans iOS 6, je ne sais pas comment faire. J'ai essayé ce qui suit posté ci-dessous. Quelqu'un peut-il me dire ce que je fais mal? Merci!

-(BOOL)shouldAutorotate {
return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{

return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
} 

J'ai aussi essayé:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(didRotate:)
                                            name:UIDeviceOrientationDidChangeNotification
                                           object:nil];
return YES;//UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
} 


 -(void)didRotate:(NSNotification *)notification {
 UIDeviceOrientation orientation = [[notification object] orientation];

if (orientation == UIDeviceOrientationLandscapeLeft) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
} else if (orientation == UIDeviceOrientationLandscapeRight) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortrait) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
}
}
27
Alex G

Cela a fonctionné pour moi Comment forcer un UIViewController à l’orientation Portrait dans iOS 6

Créez une nouvelle catégorie à partir de UINavigationController en remplaçant les méthodes de rotation:

-(BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

@end 
19
ChavirA

Il y a des changements dans iOS 6 concernant la gestion des rotations de vues. Seules les orientations définies dans les applications Info.plist sont prises en charge. Même si vous retournez d'autres.

Essayez de sélectionner toutes les orientations comme supportées dans votre projet.

Gestion des rotations de vues

Dans iOS 6, votre application prend en charge les orientations d’interface définies dans le fichier Info.plist de votre application. Un contrôleur de vue peut remplacer la méthode supportedInterfaceOrientations pour limiter la liste des orientations prises en charge. Généralement, le système appelle cette méthode uniquement sur le contrôleur de vue racine de la fenêtre ou sur un contrôleur de vue présenté pour remplir la totalité de l'écran. Les contrôleurs de vue enfants utilisent la partie de la fenêtre qui leur est fournie par leur contrôleur de vue parent et ne participent plus directement aux décisions concernant les rotations prises en charge. L’intersection du masque d’orientation de l’application et du masque d’orientation du contrôleur de vue sert à déterminer les orientations dans lesquelles le contrôleur de vue peut être pivoté.

Vous pouvez remplacer la preferredInterfaceOrientationForPresentation pour un contrôleur de vue destiné à être présenté en plein écran dans une orientation spécifique.

Dans iOS 5 et les versions antérieures, la classe UIViewController affiche uniquement les vues en mode portrait. Pour prendre en charge d'autres orientations, vous devez remplacer la méthode shouldAutorotateToInterfaceOrientation: et renvoyer YES pour toute orientation prise en charge par votre sous-classe. Si les propriétés de redimensionnement automatique de vos vues sont correctement configurées, il vous suffira peut-être de le faire. Cependant, la classe UIViewController fournit des points d'ancrage supplémentaires pour vous permettre d'implémenter des comportements supplémentaires en fonction des besoins. En règle générale, si votre contrôleur de vue est destiné à être utilisé comme contrôleur de vue enfant, il doit prendre en charge toutes les orientations de l'interface.

Lorsqu'une rotation se produit pour un contrôleur de vue visible, les méthodes willRotateToInterfaceOrientation:duration :, willAnimateRotationToInterfaceOrientation:duration: et didRotateFromInterfaceOrientation: sont appelées pendant la rotation. La méthode viewWillLayoutSubviews est également appelée une fois la vue redimensionnée et positionnée par son parent. Si un contrôleur de vue n'est pas visible lorsqu'un changement d'orientation se produit, les méthodes de rotation ne sont jamais appelées. Cependant, la méthode viewWillLayoutSubviews est appelée lorsque la vue devient visible. Votre implémentation de cette méthode peut appeler la méthode statusBarOrientation pour déterminer l'orientation du périphérique.

(C) Apple Docs: UIViewController

6
Nekto

Suivez les étapes ci-dessous

  • Créez une sous-classe de UINavigationController en remplaçant les méthodes en rotation.
  • Dans AppDelegate, créez une propriété BOOL islandscape.
  • Lorsqu'une vue est poussée/affichée/présente/supprimée, ajustez cette valeur BOOL.

Exemple de projet

J'ai créé pour cela un exemple de projet qui fonctionne parfaitement. Téléchargez et intégrez dans votre projet: https://www.dropbox.com/s/nl1wicbx52veq41/RotationDmeo.zip?dl=0

2
pkc456

J'ai un:

TabbarController -> NavigationController -> ViewController -> ViewController

J'ai sous-classé UITabBarController et ajouter ....

-(NSUInteger)supportedInterfaceOrientations{
    if (self.selectedIndex >= 0 && self.selectedIndex < 100) {
        for (id vC in [[self.viewControllers objectAtIndex:(unsigned long)self.selectedIndex] viewControllers]) {
            if ([vC isKindOfClass:[CLASS_WHICH_SHOULD_ALLOW class]]) {
                return UIInterfaceOrientationMaskPortrait + UIInterfaceOrientationMaskLandscape;
            }
        }
    }
    
    return UIInterfaceOrientationMaskPortrait;
}

0
Kurt57

Je cherche la solution depuis des heures! 

Donc, après avoir mis en œuvre les méthodes nécessaires partout. shouldAutorotate n'a pas besoin d'être défini sur YES car il est déjà défini par défaut:

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
     return UIInterfaceOrientationPortrait;
}

Lorsqu'il est temps d'afficher la UIViewController qui nécessite une orientation différente de celle des autres vues, j'ai créé une UIStoryboardSegue avec cette implémentation à l'intérieur: 

#import "Showing.h"

@implementation Showing

- (void)perform{
    NSLog(@"Showing");
    UIViewController *sourceVC = self.sourceViewController;
    UIViewController *presentingVC = self.destinationViewController;

    [sourceVC.navigationController presentViewController:presentingVC 
                                                animated:YES 
                                              completion:nil];
}

@end

À l'intérieur de la UIStoryboard, j'ai relié les vues à cette séquence (montrant):

enter image description here

C'est juste important, vous utilisez

presentViewController:animated:completion:

ET PAS

pushViewController:animated:

sinon l'orientation ne sera pas déterminée à nouveau .


J'avais essayé des choses comme

[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];

OU celui-ci à l'intérieur de la UIViewController où l'orientation devrait changer, et j'ai aussi essayé de l'appeler dans ma coutume UIStoryboardSegues avant presentingViewController et dismissViewController:

[UIViewController attemptRotationToDeviceOrientation];

OU

NSNumber *numPortrait = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:numPortrait forKey:@"orientation"];

Mais aucun d'entre eux n'a travaillé. Bien sûr, le dernier exemple ne devrait pas être une option, car si Apple modifiait quoi que ce soit de son API, cela pourrait poser des problèmes au sein de votre application.

J'ai également essayé d'utiliser la méthode AppDelegate et de toujours déterminer l'orientation à l'intérieur de cette méthode après avoir recherché la bonne UIInterfaceOrientation de la visibleViewController réelle, mais il arrivait parfois qu'il y ait un blocage lors du passage d'une orientation à une autre. Je me demande donc toujours pourquoi cela est si compliqué et qu'il semble également ne pas y avoir de documentation où elle est expliquée correctement ... Même après cette partie ne m'a pas aidé moi.

0
Alex Cio

UIViewController + OrientationPermissions.h

@interface UIViewController (OrientationPermissions)
   + (void)setSupportedOrientations:(UIInterfaceOrientationMask)supportedOrientations;
   + (UIInterfaceOrientationMask)supportedOrientations;
@end

UIViewController + OrientationPermissions.m

@implementation UIViewController (OrientationPermissions)
static UIInterfaceOrientationMask _supportedOrientations;

+ (void)setSupportedOrientations:    (UIInterfaceOrientationMask)supportedOrientations {
    _supportedOrientations = supportedOrientations;
}

+ (UIInterfaceOrientationMask)supportedOrientations {
    return _supportedOrientations;
}

@end

Dans votre délégué UIApplication

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return [UIViewController supportedOrientations];
}

Ensuite, sur un contrôleur de vue souhaité, faites quelque chose comme

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [UIViewController setSupportedOrientations:UIInterfaceOrientationMaskAll];
}

N'oubliez pas de réinitialiser le masque avant de quitter ce contrôleur de vue 

Notez que si vous utilisez UINavigationController ou UITabBarController, voir https://stackoverflow.com/a/28220616/821994 comment contourner ce problème

0