GeckoGeek.fr

Paradigme d'un lézard

Mardi 16 Septembre 2014

iPhone : Forcer le mode Landscape ou Portrait en cours d’exécution

Par Lya le 10/09/2010 dans Apple, Programmation | 1 commentaire

Vous pouvez choisir de fixer l’orientation de l’iphone pour votre application lors de son lancement. Par exemple dans beaucoup de cas, un jeu aura besoin de se lancer en mode landscape. Cela se paramètre dans le plist du projet. Mais dans des cas particuliers, vous pourriez avoir besoin de fixer l’orientation du device en cours d’exécution de votre application. Par exemple lancer l’application en mode portrait et vouloir, pour une vue donnée, passer en mode landscape (ce qui force l’utilisateur à tourner le device, d’où le cas exceptionnel de cet emploi : il faut vraiment que ça se justifie). La méthode setOrientation (de UIDevice) étant privée, voici une autre manière de l’effectuer.

Le Principe

Le principe est très simple : il est possible de le faire, mais il faut que le View Controller en question soit ajouté à la fenêtre “window” de l’AppDelegate. Ensuite il suffit d’indiquer dans la méthode “shouldAutorotateToInterfaceOrientation” que l’on veut un mode landscape pour cette view.

L’utilisateur est en mode portrait. La nouvelle vue qui arrive est en mode landscape, donc l’utilisateur tourne le device. Les vue suivantes resteront en landscape car le device est maintenant détecté en mode landscape (rotation).

Exemple de code

Pour illustrer cette fonctionnalité, nous allons réaliser l’application qui est représentée dans l’image ci-dessus. L’application s’ouvre sur une vue en mode portrait qui possède un label et un bouton. Le bouton envoie sur une nouvelle vue. Cette dernière est en mode landscape, et possède elle aussi un label et un bouton (qui renvoie sur la première vue).

Création des deux ViewControllers

Commençons par créer les deux View Controllers. Le premier s’appelera PortraitViewController, le second LandscapeViewController.

Voici le .h (c’est le même pour le second, échangez juste les noms portrait / landscape). On y place le label, le bouton, et la méthode qui est appelée quand le bouton est touché.

#import <UIKit/UIKit.h>

@interface PortraitViewController : UIViewController {

	// View elements
	UILabel *labelPortrait;
	UIButton *buttonSwitchToLandscape;

}
- (void)go2LandscapeView:(id)sender;

@end

On ajoute le label et le bouton dans le loadView du .m (la largeur et la hauteur des frames ne sont pas les mêmes selon le mode).

- (void)loadView {
	
	// Create Main View
	[ super loadView ];
	[ self.view setFrame:CGRectMake(0.0, 0.0, 320.0, 480.0) ];
	[ self.view setBackgroundColor:[ UIColor whiteColor ] ];
	
	// Label
	labelPortrait = [ [ UILabel alloc ] initWithFrame:CGRectMake(0.0, 150.0, 320.0, 30.0) ];
	[ labelPortrait setFont:[ UIFont boldSystemFontOfSize:22.0 ] ];
	[ labelPortrait setTextAlignment:UITextAlignmentCenter ];
	[ labelPortrait setBackgroundColor:[ UIColor clearColor ] ];
	[ labelPortrait setText:@"I'm a view in Portrait mode" ];
	[ self.view addSubview:[ labelPortrait autorelease ] ];	

	// Button  
	buttonSwitchToLandscape = [ UIButton buttonWithType:UIButtonTypeRoundedRect ];
	[ buttonSwitchToLandscape setTitle:@"Go to a Landscape View" forState:UIControlStateNormal ];
	[ buttonSwitchToLandscape setFrame:CGRectMake(60.0, 200.0, 200.0, 40.0) ];
	[ buttonSwitchToLandscape setShowsTouchWhenHighlighted:YES ];
	[ buttonSwitchToLandscape addTarget:self action:@selector(go2LandscapeView:) 
						forControlEvents:UIControlEventTouchUpInside ];
	[ self.view addSubview:buttonSwitchToLandscape ];

}

Faites la même chose pour le second View Controller : LandscapeViewController.

Ajout de l’appel au delegate

N’oubliez pas qu’il faut que ça soit le delegate qui gère l’échange des views, afin de pouvoir les ajouter à “window”. Pour cela, on l’ajoute dans les .h des View Controllers : #import “AppDelegate.h”.

Et donc dans la méthode du bouton, on appelle une méthode qui se trouve dans le delegate (et que l’on va écrire bientôt) :

[ (AppDelegate*)[ [ UIApplication sharedApplication ] delegate ] switchToLandscapeView ];

(Pareillement pour le second View Controller.)

L’AppDelegate

Du côté du delegate, on doit donc ajouter ces deux fonctions. Elles vont retirer la vue actuelle, désallouer le View Controller, allouer le nouveau et mettre sa view à la place. Voici l’exemple pour la première :

- (void)switchToLandscapeView {
	
	[ vcPortrait.view removeFromSuperview ];
	[ vcPortrait release ];
	vcPortrait = nil;

	vcLandscape = [ [ LandscapeViewController alloc ] init ];
	[ window addSubview:vcLandscape.view ];
	
}

N’oubliez pas d’ajouter une des deux vues par défaut à la création de l’app delegate qui apparaîtra au lancement de l’application. Dans notre exemple, ça sera la vue de vcPortait.

Le sens d’orientation

Il ne reste plus qu’à fixer le sens d’orientation dans vcLandscape :

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	
	// Force the landscape mode 
	return UIDeviceOrientationIsLandscape(interfaceOrientation);
	
}

Récapitulatif

Voici l’ensemble du code des fichiers que nous venons de voir :

AppDelegate

// Created by GeckoGeek on 09/09/10
// AppDelegate.h
#import <UIKit/UIKit.h>

@class PortraitViewController;
@class LandscapeViewController;

@interface AppDelegate : NSObject <UIApplicationDelegate> {
	
    UIWindow *window;

	// Controllers
    PortraitViewController *vcPortrait;
	LandscapeViewController *vcLandscape;

}
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, assign) PortraitViewController *vcPortrait;
@property (nonatomic, assign) LandscapeViewController *vcLandscape;

- (void)loadPortraitView;
- (void)switchToLandscapeView;
- (void)switchToPortraitView;

@end

// Created by GeckoGeek on 09/09/10
// AppDelegate.m
#import "AppDelegate.h"
#import "PortraitViewController.h"
#import "LandscapeViewController.h"

@implementation AppDelegate

@synthesize window, vcPortrait, vcLandscape;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
								(NSDictionary *)launchOptions {    
    
	// Init Window
	self.window = [ [ [ UIWindow alloc ] initWithFrame:[ [ UIScreen mainScreen ] bounds ] ] 
								autorelease ];
    
	// Init Controllers
	vcPortrait = nil;	
	vcLandscape = nil;

	[ self loadPortraitView ];
	
	// Display
    [ window makeKeyAndVisible ];

    return YES;

}

- (void)switchToLandscapeView {
	
	[ vcPortrait.view removeFromSuperview ];
	[ vcPortrait release ];
	vcPortrait = nil;

	vcLandscape = [ [ LandscapeViewController alloc ] init ];
	[ window addSubview:vcLandscape.view ];
	
}

- (void)switchToPortraitView {
	
	if (vcLandscape != nil) {
		
		[ vcLandscape.view removeFromSuperview ];
		[ vcLandscape release ];
		vcLandscape = nil;
		
	}
	
	[ self loadPortraitView ];
		
}

- (void)loadPortraitView {

	vcPortrait = [ [ PortraitViewController alloc ] init ];
	[ window addSubview:vcPortrait.view ];
	
}

- (void)dealloc {
	
	// Dealloc Portrait View Controller if necessary
	if (vcPortrait != nil) {
		[ vcPortrait.view removeFromSuperview ];
		[ vcPortrait release ];
		vcPortrait = nil;		
	}

	// Dealloc Landscape View Controller if necessary
	if (vcLandscape != nil) {
		[ vcLandscape.view removeFromSuperview ];
		[ vcLandscape release ];
		vcLandscape = nil;		
	}
	
    [ window release ];
    [ super dealloc ];

}

@end

PortraitViewController

// Created by GeckoGeek on 09/09/10
// PortraitViewController.h
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

@interface PortraitViewController : UIViewController {

	// View elements
	UILabel *labelPortrait;
	UIButton *buttonSwitchToLandscape;

}
- (void)go2LandscapeView:(id)sender;

@end

// Created by GeckoGeek on 09/09/10
// PortraitViewController.m
#import "PortraitViewController.h"

@implementation PortraitViewController

- (id)init {
	
	if (self = [ super init ]) {

		labelPortrait = nil;
		buttonSwitchToLandscape = nil;

	}

	return self;
	
}

- (void)loadView {
	
	// Create Main View
	[ super loadView ];
	[ self.view setFrame:CGRectMake(0.0, 0.0, 320.0, 480.0) ];
	[ self.view setBackgroundColor:[ UIColor whiteColor ] ];
	
	// Label
	labelPortrait = [ [ UILabel alloc ] initWithFrame:CGRectMake(0.0, 150.0, 320.0, 30.0) ];
	[ labelPortrait setFont:[ UIFont boldSystemFontOfSize:22.0 ] ];
	[ labelPortrait setTextAlignment:UITextAlignmentCenter ];
	[ labelPortrait setBackgroundColor:[ UIColor clearColor ] ];
	[ labelPortrait setText:@"I'm a view in Portrait mode" ];
	[ self.view addSubview:[ labelPortrait autorelease ] ];	

	// Button  
	buttonSwitchToLandscape = [ UIButton buttonWithType:UIButtonTypeRoundedRect ];
	[ buttonSwitchToLandscape setTitle:@"Go to a Landscape View" forState:UIControlStateNormal ];
	[ buttonSwitchToLandscape setFrame:CGRectMake(60.0, 200.0, 200.0, 40.0) ];
	[ buttonSwitchToLandscape setShowsTouchWhenHighlighted:YES ];
	[ buttonSwitchToLandscape addTarget:self action:@selector(go2LandscapeView:) 
						forControlEvents:UIControlEventTouchUpInside ];
	[ self.view addSubview:buttonSwitchToLandscape ];

}

- (void)go2LandscapeView:(id)sender {
	
	// Call the switch method of the app delegate
	[ (AppDelegate*)[ [ UIApplication sharedApplication ] delegate ] switchToLandscapeView ];
	
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

	return UIInterfaceOrientationIsPortrait(interfaceOrientation);
	
}

- (void)viewDidUnload {
	
	labelPortrait = nil;
	buttonSwitchToLandscape = nil;
	
}

- (void)dealloc {
	
	NSLog(@"Dealloc Portrait View Controller");	
    [ super dealloc ];

}

@end

LandscapeViewController

// Created by GeckoGeek on 09/09/10
// LandscapeViewController.h
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

@interface LandscapeViewController : UIViewController {
	
	UILabel *labelLandscape;	
	UIButton *buttonSwitchToPortrait;

}

- (void)go2PortraitView:(id)sender;

@end

// Created by GeckoGeek on 09/09/10
// LandscapeViewController.m
#import "LandscapeViewController.h"

@implementation LandscapeViewController

- (id)init {
	
	if (self = [ super init ]) {
		
		labelLandscape = nil;
		buttonSwitchToPortrait = nil;
		
	}
	return self;
	
}

- (void)loadView {

	// Create Main View
	[ super loadView ];
	[ self.view setFrame:CGRectMake(0.0, 0.0, 480.0, 320.0) ];
	[ self.view setBackgroundColor:[ UIColor whiteColor ] ];
	
	// Label
	labelLandscape = [ [ UILabel alloc ] initWithFrame:CGRectMake(0.0, 100.0, 480.0, 30.0) ];
	[ labelLandscape setFont:[ UIFont boldSystemFontOfSize:22.0 ] ];
	[ labelLandscape setTextAlignment:UITextAlignmentCenter ];
	[ labelLandscape setBackgroundColor:[ UIColor clearColor ] ];
	[ labelLandscape setText:@"I'm a view in Landscape mode" ];
	[ self.view addSubview:[ labelLandscape autorelease ] ];	
	
	// Button  
	buttonSwitchToPortrait = [ UIButton buttonWithType:UIButtonTypeRoundedRect ];
	[ buttonSwitchToPortrait setTitle:@"Go to a Landscape View" forState:UIControlStateNormal ];
	[ buttonSwitchToPortrait setFrame:CGRectMake(140.0, 150.0, 200.0, 40.0) ];
	[ buttonSwitchToPortrait setShowsTouchWhenHighlighted:YES ];
	[ buttonSwitchToPortrait addTarget:self action:@selector(go2PortraitView:) 
						forControlEvents:UIControlEventTouchUpInside ];
	[ self.view addSubview:buttonSwitchToPortrait ];
	
}

- (void)go2PortraitView:(id)sender {
	
	// Call the switch method of the app delegate
	[ (AppDelegate*)[ [ UIApplication sharedApplication ] delegate ] switchToPortraitView ];
	
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	
	// Force the landscape mode 
	// (it works, because this controller is added to the main window in the app delegate)
	return UIDeviceOrientationIsLandscape(interfaceOrientation);
	
}

- (void)viewDidUnload {
	
	labelLandscape = nil;
	buttonSwitchToPortrait = nil;
	
}

- (void)dealloc {
	
	NSLog(@"Dealloc Project View Controller");
    [ super dealloc ];
	
}

@end
Commentaire (1)
  1. yunas le 7 Mar 2013 à 09:32

    share project please :)


Laisser un commentaire