Je travaille sur une application iPad, avec AutoLayout, où, si l'utilisateur active un certain mode (mode "heads-up"), je souhaite uniquement prendre en charge l'orientation portrait (ou portrait à l'envers) et, de plus, si paysage, je voudrais passer automatiquement en mode portrait.
Dans le contrôleur de vue de dessus, j'ai les éléments suivants:
- (NSUInteger) supportedInterfaceOrientations {
if (self.modeHeadsUp) {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
} else {
return UIInterfaceOrientationMaskAll;
}
}
- (BOOL) shouldAutorotate {
return TRUE;
}
D'après les réponses que j'ai déjà vues ailleurs, la réponse est semble que je devrais utiliser "application setStatusBarOrientation". Par conséquent, dans la méthode où l'utilisateur a sélectionné le mode "heads-up", j'ai inclus:
UIApplication *application = [UIApplication sharedApplication];
[application setStatusBarOrientation:UIInterfaceOrientationPortrait
animated:YES];
Cependant, cela ne semble simplement rien faire. Bien que je puisse déplacer physiquement le périphérique pour le faire pivoter en portrait, il ne le fait pas automatiquement.
En fait, en mode paysage après avoir exécuté le code ci-dessus pour tenter de définir l'orientation par programme, lorsque j'interroge l'application "statusBarOrientation" avec le code suivant, il reste à "4" pour paysage:
UIApplication *application = [UIApplication sharedApplication];
int orientation = [application statusBarOrientation];
self.movesTextView.text = [NSString stringWithFormat:@"ORIENTATION %d", orientation];
Il semblait que peut-être l'autolayout n'était pas déclenché avec setStatusBarOrientation, alors j'ai essayé d'ajouter ce code après, sans aucun effet:
[super updateViewConstraints];
[self.view updateConstraints];
Je me rends compte que Apple veut laisser l'orientation de l'appareil entre les mains de l'utilisateur. Toutefois, j'aimerais pouvoir prendre en charge le mode paysage lorsque vous n'êtes pas en mode "heads-up".
Est-ce que je manque quelque chose pour pouvoir forcer le changement d'orientation?
Pour iOS 7 et 8:
Objectif c:
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
Swift 3+:
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
Je l'appelle dans - viewDidAppear:
.
Utilisez ceci. Solution parfaite au problème d'orientation..ios7 et plus tôt
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:@"orientation"];
Vous devez appeler attemptRotationToDeviceOrientation (UIViewController)
pour que le système appelle votre supportedInterfaceOrientations
lorsque la condition a changé.
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
fonctionne, mais vous devez retourner DevraitAutoriser avec OUI dans votre contrôleur de vue
- (BOOL)shouldAutorotate
{
return self.shouldAutoRotate;
}
Mais si vous faites cela, votre VC fera une autorotation si l’utilisateur fait pivoter le périphérique ... Je l’a donc changé en:
@property (nonatomic, assign) BOOL shouldAutoRotate;
- (BOOL)shouldAutorotate
{
return self.shouldAutoRotate;
}
et j'appelle
- (void)swithInterfaceOrientation:(UIInterfaceOrientation)orientation
{
self.rootVC.shouldAutoRotate = YES;
NSNumber *value = [NSNumber numberWithInt: orientation];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
pour forcer une nouvelle orientation avec un clic de bouton . Pour revenir en arrière devraitAutoRotate à NO, j'ai ajouté à mon rootVC
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
self.shouldAutoRotate = NO;
}
PS: Cette solution de contournement fonctionne également dans tous les simulateurs.
Cela fonctionne pour moi sur Xcode
6 & 5.
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait);
}
La seule façon qui a fonctionné pour moi est de présenter un contrôleur de vue modal factice.
UIViewController* dummyVC = [[UIViewController alloc] init];
dummyVC.view = [[UIView alloc] init];
[self presentModalViewController:dummyVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
Il sera demandé à votre VC des orientations d’interface mises à jour lorsque le contrôleur de vue modale est désactivé.
Ce qui est curieux, c’est que UINavigationController fait exactement cela lorsqu’il pousse/éclate des contrôleurs de vue enfant avec différentes orientations d’interface supportées (testé sur iOS 6.1, 7.0).
Cette solution vous permet de forcer une certaine orientation d'interface en remplaçant temporairement la valeur UIDevice.current.orientation
, puis en demandant au système de faire pivoter l'interface pour qu'elle corresponde à la rotation du périphérique:
Important: Ceci est un hack et pourrait cesser de fonctionner à tout moment
Ajoutez les éléments suivants dans le contrôleur de vue racine de votre application:
class RootViewController : UIViewController {
private var _interfaceOrientation: UIInterfaceOrientation = .portrait
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) }
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return _interfaceOrientation }
override func viewDidLoad() {
super.viewDidLoad()
// Register for notifications
NotificationCenter.default.addObserver(self, selector: #selector(RootViewController.handleInterfaceOrientationChangeRequestedNotification(_:)), name: .interfaceOrientationChangeRequested, object: nil)
}
deinit { NotificationCenter.default.removeObserver(self) }
func handleInterfaceOrientationChangeRequestedNotification(_ notification: Notification) {
guard let interfaceOrientation = notification.object as? UIInterfaceOrientation else { return }
_interfaceOrientation = interfaceOrientation
// Set device orientation
// Important:
// • Passing a UIDeviceOrientation here doesn't work, but passing a UIInterfaceOrientation does
// • This is a hack, and could stop working at any moment
UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: "orientation")
// Rotate the interface to the device orientation we just set
UIViewController.attemptRotationToDeviceOrientation()
}
}
private extension UIInterfaceOrientationMask {
init(from interfaceOrientation: UIInterfaceOrientation) {
switch interfaceOrientation {
case .portrait: self = .portrait
case .landscapeLeft: self = .landscapeLeft
case .landscapeRight: self = .landscapeRight
case .portraitUpsideDown: self = .portraitUpsideDown
case .unknown: self = .portrait
}
}
}
extension Notification.Name {
static let interfaceOrientationChangeRequested = Notification.Name(rawValue: "interfaceOrientationChangeRequested")
}
Assurez-vous que toutes les orientations de l'interface sont vérifiées sous "Informations de déploiement":
Demander les changements d'orientation de l'interface là où vous en avez besoin:
NotificationCenter.default.post(name: .interfaceOrientationChangeRequested, object: UIInterfaceOrientation.landscapeRight)
Ajouter cette déclaration dans AppDelegate.h
//whether to allow cross screen marker
@property (nonatomic, assign) allowRotation BOOL;
Notez cette section de code dans AppDelegate.m
- (UIInterfaceOrientationMask) application: (UIApplication *) supportedInterfaceOrientationsForWindow: application (UIWindow *) window {
If (self.allowRotation) {
UIInterfaceOrientationMaskAll return;
}
UIInterfaceOrientationMaskPortrait return;
}
Changer la propriété allowRotation
de l'application déléguée
Si vous avez un UIViewController qui doit rester en mode Portrait, ajoutez simplement ce remplacement et vous êtes prêt.
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
La meilleure partie est qu'il n'y a pas d'animation lorsque cette vue est affichée, elle est déjà dans la bonne orientation.
Si vous souhaitez verrouiller la vue principale de votre application sur Portrait, mais que vous souhaitez ouvrir des vues contextuelles en mode paysage et que vous utilisez tabBarController en tant que rootViewController en tant que moi, vous pouvez utiliser ce code sur votre AppDelegate.
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UITabBarController *tabBarController;
@end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Create a tab bar and set it as root view for the application
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
...
}
- (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController
{
return UIInterfaceOrientationPortrait;
}
Il fonctionne très bien.
Dans votre viewController que vous souhaitez afficher en paysage, vous utilisez simplement les éléments suivants:
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate {
return YES;
}
Le UINavigationController de base doit avoir le rappel ci-dessous afin que les éléments enfants puissent décider de l'orientation qu'ils souhaitent.
-(NSUInteger)supportedInterfaceOrientations {
UIViewController *topVC = self.topViewController;
return topVC.supportedInterfaceOrientations;
}
-(BOOL)shouldAutorotate {
UIViewController *topVC = self.topViewController;
return [topVC shouldAutorotate];
}
voici un exemple PLEIN DE TRAVAIL pour iOS 7, 8, 9, 10 comment changer l'orientation de l'application en fonction de son opposé
Objectif c
- (void)flipOrientation
{
NSNumber *value;
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if(UIInterfaceOrientationIsPortrait(currentOrientation))
{
if(currentOrientation == UIInterfaceOrientationPortrait)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown];
}
else //if(currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
}
}
else
{
if(currentOrientation == UIInterfaceOrientationLandscapeRight)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
}
else //if(currentOrientation == UIInterfaceOrientationLandscapeLeft)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
}
}
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
Swift 3
func flipOrientation() -> Void
{
let currentOrientation : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
var value : Int = 0;
if(UIInterfaceOrientationIsPortrait(currentOrientation))
{
if(currentOrientation == UIInterfaceOrientation.portrait)
{
value = UIInterfaceOrientation.portraitUpsideDown.rawValue
}
else //if(currentOrientation == UIInterfaceOrientation.portraitUpsideDown)
{
value = UIInterfaceOrientation.portrait.rawValue
}
}
else
{
if(currentOrientation == UIInterfaceOrientation.landscapeRight)
{
value = UIInterfaceOrientation.landscapeLeft.rawValue
}
else //if(currentOrientation == UIInterfaceOrientation.landscapeLeft)
{
value = UIInterfaceOrientation.landscapeRight.rawValue
}
}
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
J'étais dans un problème similaire à vous. J'ai besoin de verrouiller l'orientation de l'appareil pour certains écrans (comme Login) et de permettre la rotation des autres.
Après quelques changements et après quelques réponses ci-dessous, je l'ai fait par:
shouldAutorotate
dans ce VC:-(BOOL)shouldAutorotate{
return NO;
}
J'espère que cela fonctionnera pour vous.
Cela m'a fonctionné parfaitement ....
NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
Pour ceux qui, comme moi, avaient du mal à obtenir @Sunny Shah, acceptaient de travailler sur iPad. Vous devez activer la case à cocher "Nécessite le plein écran" dans les paramètres du projet. Notez que cela empêchera votre application de fonctionner en mode multitâche, ce qui peut être acceptable ou non.
Essayez ceci avec votre code.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
une fois que l'utilisateur sélectionne une option, appelez cette méthode, car il peut être en mode paysage, puis il ne peut définir que le mode portrait dans le même contrôleur de vue. La vue doit donc automatiquement être déplacée en mode portrait.
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration