Toutes les composantes graphiques proposées par UIKit
pour réaliser les interfaces des applications iOS sont des vues. Certaines sont très simples (comme un champ texte), certaines réagissent aux interactions de l’utilisateur (comme un bouton) et d’autres sont extrêmement complexes (comme la vue web qui permet d’afficher des contenus HTML), mais elles descendent toutes de la classe UIView
.
Dans ce chapitre, nous présenterons la classe UIView
, ses propriétés et son fonctionnement. Nous expliquerons comment composer des vues complexes à partir de vues simples, les composants graphiques les plus importants et enfin nous verrons comment internationaliser les vues de votre application.
Une vue est un objet qui dérive de la classe UIView
. Elle représente une sous-partie de sa vue parente.
Sur iOS, les coordonnées sont toujours mesurées en points, avec une origine située en haut à gauche. L’axe X est horizontal et l’axe Y est vertical.
Ainsi, en supposant que l’iPhone est tenu verticalement :
• (0,0) représente le coin supérieur gauche ;
• (320,0) le coin supérieur droit ;
• (0,480) le coin inférieur gauche ;
• (320,480) le coin inférieur droit.
Bien entendu, les dimensions de l’écran sont 1024 et 768 pour un iPad, 320 et 568 pour un iPhone 5.
La zone occupée par une vue est définie par la position du centre de cette dernière (propriété center
de type CGPoint)
et ses limites (largeur et hauteur, propriété bounds
de type CGRect
).
UIView *view = [[UIView alloc] init] ;
view.bounds = CGRectMake(0, 0, 100, 50) ;
view.center = CGPointMake(160,100) ;
UIView *view = [[UIView alloc] init];
view.bounds = CGRectMake(0, 0, 100,50);
view.center = CGPointMake(160,100);
ATTENTION Origine des coordonnées
Le centre est toujours mesuré dans le système de coordonnées de la vue parente.
Figure 9–1 Centre, taille et position d’une vue
ATTENTION Limites de la vue
Il est possible d’exploiter l’origine du rectangle de la propriété bounds
pour forcer la vue à ne dessiner qu’une partie d’elle-même. Dans la plupart des cas cependant, l’origine utilisée est (0,0) ce qui revient à définir la largeur et la hauteur.
Les coordonnées d’une vue peuvent également être exprimées sous forme d’un rectangle (frame). Dans ce cas, on donne la position du coin supérieur gauche, puis la largeur et la hauteur de la vue.
Vous accédez au rectangle représentant la vue grâce à la propriété frame
de type CGRect
. Elle est accessible en lecture et en écriture (les propriétés center
et bounds
sont synchronisées automatiquement).
// Équivalent de l’exemple précédent.
view.frame = CGRectMake(110, 75, 100, 50);
Figure 9–2 Coordonnées en utilisant la frame plutôt que le centre et la taille
ATTENTION Bonne utilisation de la propriété frame
La propriété frame
étant plus naturelle à manipuler, on l’utilisera plus souvent que les propriétés bounds
et center
.
Il existe pourtant des cas pour lesquels elle n’est plus du tout équivalente aux propriétés bounds
et center
, en particulier, dès qu’une transformation (rotation ou zoom) est effectuée sur une vue grâce à la propriété transform
.
Les vues forment un arbre dont la racine est la fenêtre de l’application (qui est également une vue).
Chaque vue peut contenir des vues filles et garde une référence vers sa vue parente.
Figure 9–3 Hiérarchie des vues
Pour récupérer la référence vers la vue parente, on utilise la propriété parentView.
Pour ajouter une sous-vue à une vue, on utilise la méthode addSubview:
et pour lister les sous-vues, il existe la propriété subviews.
Une vue peut gérer le positionnement de ses sous-vues et ajuster leur position quand sa taille change.
Ce travail est réalisé dans la méthode layoutSubviews,
qui ne doit jamais être appelée directement. On demande à ce qu’elle soit appelée par le sous-système d’affichage des vues en invoquant la méthode setNeedsLayout.
L’implémentation par défaut de layoutSubviews
s’appuie sur deux propriétés qui précisent à la méthode son comportement :
• autoresizeSubviews
indique si elle doit ou pas essayer de redimensionner les sous-vues ;
• autoresizingMask
indique quels sont les ajustements que la vue peut faire.
Cette dernière propriété s’appuie sur les valeurs suivantes, qui peuvent être combinées avec l’opérateur binaire OU.
Valeur | Comportement |
UIAutoresizeMaskFlexibleHeight |
Indiquent que la hauteur et/ou la largeur de la vue peuvent être ajustées. |
UIAutoresizeMaskFlexibleMarginLeft |
Indiquent que certaines des marges de la vue peuvent être agrandies ou rétrécies. |
Avant iOS 6, le changement d’orientation, appelé springs and struts, demandait de la part du développeur de nombreuses lignes de code. En effet, les objets se positionnaient à partir des marges appelées springs et possédaient leurs dimensions propres (largeur, hauteur) appelées struts. Le principal problème était la relation qui pouvait exister entre différents objets et les contraintes d’interdépendances qui en découlaient. Avec iOS 6, on possède un mécanisme plus complet de contrôle du positionnement des éléments les uns par rapport aux autres comme dans l’exemple suivant.
Figure 9–4 Exemples de contraintes avant et après iOS 6
On peut voir dans le premier exemple que les objets sont « ancrés » en haut à gauche et que, lors de la rotation, l’effet produit est désastreux. Le nombre de lignes de code associées aux contraintes habituelles est assez complexe à mettre en œuvre. Dans le second exemple, il est bien plus facile de décider de l’espacement des objets les uns par rapport aux autres.
Pour cela, Apple a créé une nouvelle classe intitulée NSLayoutConstraint
qui aide à positionner les objets plus précisément et, accessoirement, résout le problème de la nouvelle définition de l’iPhone 5.
Par exemple, pour modifier l’espacement entre les deux vues supérieures, on peut procéder de la façon suivante :
1 Sélectionner la contrainte entre les deux vues,
2 Dans l’Attribute Inspector, modifier la constante (par exemple en la passant à 75) et supprimer la sélection Standard comme dans l’exemple qui suit.
3 Et recompiler simplement votre projet. C’est aussi simple que cela.
On peut noter que les contraintes sont globales à une scène du Storyboard.
Figure 9–5 Modification d’une contrainte d’espacement et résultat dans le simulateur
UIKit
fournit de nombreuses vues que vous pouvez composer ensemble pour créer des interfaces iOS riches. Nous ne passerons en revue ici que les éléments les plus essentiels.
La partie graphique de Xcode permettant la composition par storyboards est un excellent moyen de découvrir les nombreux composants et les possibilités de paramétrage. Vous devriez également installer sur votre iPhone l’application UICatalog fournie par Apple dans les exemples de code du SDK et qui permet de voir en action sur le téléphone toutes les vues standards.
Les vues élémentaires de l’UIKit sont pour la plupart affichées au-dessus de la vue principale. On peut les déclarer en weak
, ce qui évite de gérer le pointeur vers nil
lorsqu’on cesse leur utilisation.
Voici un exemple pour un label :
@property(nonatomic,weak) IBOutlet UILabel *unLabel ;
La classe UILabel
sert à afficher un texte à l’écran. Le développeur peut choisir la taille du texte, sa couleur, comment l’aligner et, éventuellement, le tronquer.
Propriété | Effet |
text |
Texte à afficher. |
font |
Police à utiliser pour afficher le texte. |
textColor |
Couleur du texte. |
textAlignment |
Mode d’alignement du texte : UITextAlignmentLeft , UITextAlignmentCenter , UITextAlignmentRight . |
shadowOffset |
Décalage entre le texte et son ombre. |
shadowColor |
Couleur de l’ombre. |
Exemple d’utilisation de UILabel
UILabel *myLabel =
[[UILabel alloc] initWithFrame:CGRectMake(20,20, 100, 20];
myLabel.text = @"TestLabel";
myLabel.textColor = [UIColor blackColor];
myLabel.textAlignment = UITextAlignmentCenter;
myLabel.font = [UIFont fontWithName:@"Helvetica" size:14];
myLabel.shadowOffset = CGSizeMake(-1.0, 0.0);
myLabel.shadowColor =
[[UIColor blackColor] colorWithAlphaComponent:0.3];
[mainView addSubview:myLabel];
ASTUCE Couleur et transparence
La méthode colorWithAlphaComponent:
de la classe UIColor
définit une couleur avec transparence à partir d’une couleur standard. La couleur clearColor
(obtenue grâce à [UIColor clearColor]
) est complètement transparente.
Il est ainsi très facile de préparer des interfaces très riches et qui utilisent abondamment les transparences. Votre seule limite sera alors celle des performances de l’appareil.
La vue utilisant la classe UIImageView
affiche une image, qui peut être embarquée dans votre projet comme un fichier dans le groupe Supporting Files par exemple. Les principaux formats d’images pris en charge par l’iPhone sont le PNG, le JPEG et le GIF (la liste complète est disponible dans la documentation de UIImage
).
CONSEIL Utilisez le format PNG
Le format PNG est le plus efficace sous iOS.
Le problème inhérent aux fichiers JPEG est que ce type d’encodage ne travaille pas dans l’espace de couleurs RGB mais dans une variante de l’espace de couleurs YCbCr. De fait, il faut une opération supplémentaire lors du décodage (conversion YCbCr vers RGB) par rapport à un PNG 24 ou 32 bits qui, lui, encode les données directement en RGB (au prix d’une efficacité de compression plus faible).
Par ailleurs, lors de la création de l’application, Xcode va optimiser les fichiers PNG grâce à l’utilitaire pngcrush
réduisant leur taille (d’autres optimisations peuvent être appliquées, qui réduisent le temps de chargement, par exemple prémultiplication d’alpha pour les PNG 32 bits).
En pratique, il est très fortement conseillé de préparer toutes vos ressources en PNG et de ne pas utiliser d’autres formats d’images.
Pour créer une vue UIImageView
, il faut lui passer en paramètre un objet UIImage
qui est la représentation en mémoire de toutes les images pour UIKit
.
Exemple d’utilisation de UIImageView
UIImageView *imageView =
[[UIImageView alloc] initWithImage:
[UIImage imageNamed:@"myimage.png"]];
[mainView addSubview:imageView];
En utilisant la propriété contentMode
(de type UIViewContentMode
), on définit comment l’image doit être ajustée par rapport à la taille de la vue.
Exemple d’utilisation de UIImageView
en forçant la taille de la zone d’affichage
UIImageView *imageView =
[[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 300, 460)];
imageView.image = [UIImage imageNamed:@myimage.png"];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[mainView addSubview:imageView];
La classe UIButton
affiche une zone cliquable. Il est possible d’utiliser le style par défaut ou un des styles prédéfinis, ou bien de fournir vos propres images pour représenter les différents états du bouton. Le bouton utilise le design pattern Target-Action.
Nous avons déjà vu dans le chapitre 7 traitant des contrôleurs de vues comment mettre en place une action exécutée lorsque le bouton est utilisé (via le mécanisme cible-action). On initialise un bouton à l’aide de la méthode buttonWithType:
; la liste des types disponibles est détaillée dans la documentation, mais le plus important est UIButtonTypeCustom.
Dans ce cas, le bouton créé est complètement transparent.
Il est alors possible de définir l’image à utiliser pour chaque état du bouton :
• UIControlStateNormal;
• UIControlStateHighlighted
(l’utilisateur a cliqué sur le bouton);
• UIControlStateDisabled
(le bouton est désactivé).
On définit l’image à utiliser à l’aide de la méthode suivante :
setImage:(UIImage*) forState:(UIControlState)
Exemple d’utilisation de UIButton
- (void) actionDuBouton:(UIButton *)sender {
self.view.backgroundColor = [UIColor greenColor];
}
- (void) viewDidLoad {
// …
UIButton *unBouton =
[UIButton buttonWithType:UIButtonTypeRoundedRect];
unBouton.frame = CGRectMake(20, 300, 200, 30);
[unBouton setTitle:@"Clic" forState:UIControlStateNormal];
[unBouton setTitle:@"Pressé !" forState:UIControlStateHighlighted];
[unBouton setTitleColor:[UIColor blackColor]
forState:UIControlStateNormal];
[unBouton setOpaque:NO];
[unBouton setAlpha:1];
[unBouton addTarget:self
action:@selector(actionDuBouton:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:unBouton];
}
Le bouton est d’abord créé.
Puis il est placé à l’écran dans un cadre (frame).
Ensuite, un titre est associé au bouton en fonction de son état (au départ).
Puis lorsqu’il est pressé.
Le bouton possède de nombreuses propriétés que l’on retrouve dans la documentation ; ici, on choisit une couleur de police de caractères, son opacité et son niveau de transparence.
Le bouton est associé à une méthode lorsqu’il est pressé (
TouchUpInside
).
Puis le bouton est placé dans la vue courante par l’appel à la méthode
addSubview:.
La classe UITextField
définit une zone dans laquelle l’utilisateur pourra saisir du texte. Lorsqu’il cliquera dans cette zone, le clavier apparaîtra automatiquement. Votre application doit, si nécessaire, déplacer les autres éléments à l’écran pour s’assurer que le clavier n’est pas venu par-dessus la zone de texte.
Pour avoir un contrôle fin de l’édition, votre contrôleur doit s’enregistrer comme délégué de la zone de texte. Pour cela, il doit implémenter le protocole UITextFieldDelegate.
La méthode textFieldShouldReturn:
de ce délégué est appelée quand l’utilisateur a fini d’éditer le texte. Pour faire disparaître le clavier, vous pouvez alors appeler la méthode resignFirstResponder:
de la zone de texte.
Exemple d’utilisation des zones de texte
- (void) loadView
{
// …
UITextField *textField = [[UITextField alloc]
initWithFrame:CGRectMake(20, 20, 100, 20)];
UITextField *textField = [[UITextField alloc]
initWithFrame:CGRectMake(20, 20, 100, 20)];
textField.delegate = self;
[view addSubview:textField];
// …
}
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
NSLog(@"Le texte saisi par l’utilisateur est %@", textField.text);
[textField resignFirstResponder];
return YES;
}
Les boutons segmentés de la classe UISegmentedControl
servent à effectuer un choix parmi une liste de différentes possibilités sans avoir à utiliser de mécanismes plus complexes comme le PickerView
ou la TableView
.
Figure 9–6 Exemple de boutons segmentés
Il suffit de donner une liste de type NSArray
contenant les identifiants des différents boutons (ne pas oublier de terminer par nil
), puis d’appeler une fonction pour l’événement UIControlEventValueChanged
.
Les boutons segmentés utilisent le design pattern Target-Action.
Exemple d’utilisation des boutons segmentés
- (IBAction) actionDuBoutonSegmente:(UISegmentedControl *)sender {
UISegmentedControl *segmentedControl = sender;
NSLog(@"Valeur renvoyée : %lu",
(unsigned long)
[segmentedControl selectedSegmentIndex]);
switch ([segmentedControl selectedSegmentIndex]) {
case 0:
[self.view setBackgroundColor:[UIColor blueColor]];
break;
case 1:
[self.view setBackgroundColor:[UIColor greenColor]];
break;
case 2:
[self.view setBackgroundColor:[UIColor redColor]];
break;
default:
break;
}
}
- (void) viewDidLoad {
// …
NSArray *items = [NSArray arrayWithObjects:@"Un",
@"Deux",
@"Trois",
nil];
UISegmentedControl *unBoutonSegmente =
[[UISegmentedControl alloc] initWithItems:items];
unBoutonSegmente.frame = CGRectMake(20, 150, 200, 40);
[unBoutonSegmente addTarget:self
action:@selector(actionDuBoutonSegmente:)
forControlEvents:UIControlEventValueChanged];
[self.view addSubview:unBoutonSegmente];
// …
}
Lorsqu’on récupère le pointeur du bouton segmenté, on peut connaître l’index du bouton sélectionné (sous forme d’entier).
Les commutateurs (UISwitch
) proposent à l’utilisateur un choix de type I/O (Yes/No). On ne peut pas changer le label d’un commutateur.
Figure 9–7 Exemple de commutateur
On associe une action à un commutateur (soit dans l’interface graphique, soit dans le code) et on peut utiliser l’attribut on
pour connaître l’état du commutateur.
Les commutateurs utilisent le design pattern Target-Action.
Exemple d’utilisation d’un commutateur dans le fichier d’implémentation (.m
)
- (void) actionDuSwitch:(UISwitch *)sender {
if (sender.on) {
self.view.backgroundColor = [UIColor redColor];
} else {
self.view.backgroundColor = [UIColor blueColor];
}
}
- (void) viewDidLoad {
// …
UISwitch *unSwitch = [[UISwitch alloc]
initWithFrame:CGRectMake(20, 100, 100, 40)];
[unSwitch addTarget:self action:@selector(actionDuSwitch:)
forControlEvents:UIControlEventValueChanged];
[self.view addSubview:unSwitch];
// …
}
Notez que les commutateurs ne proposent par défaut que YES/NO ou O/I. Il est désormais possible de modifier la vue de chacune des positions du commutateur. Pour cela, on doit créer deux images, une pour la position on, l’autre pour la position off. On peut ajouter n’importe quel texte ou descriptif à ces images. On peut alors les associer au commutateur de la façon suivante :
Exemple de modification dans le fichier d’implémentation (.m
)
- (void)viewDidLoad {
[super viewDidLoad];
// Départ du viewcontroller
// Customization du bouton
// Par exemple dans le viewDidLoad()
[self.unSwitchCustom setOnImage:[UIImage imageNamed:@"on.png"]];
[self.unSwitchCustom setOffImage:[UIImage imageNamed:@"off.png"]];
}
Il est parfois nécessaire de faire défiler une vue au-delà des limites de l’écran. La scrollview (UIScrollView
) présente à l’utilisateur une vue de taille supérieure à celle de l’affichage en glissant la vue avec le doigt.
Elle permet également d’effectuer un zoom en pinçant l’écran (pinch) en utilisant son délégué et les propriétés maximumZoomScale
et minimumZoomScale
.
Figure 9–8 Structure d’une scrollview
Exemple d’utilisation d’une scrollview dans le fichier d’implémentation (.m
)
- (void) viewDidLoad {
// …
maScrollView =
[[UIScrollView alloc] initWithFrame:CGRectMake(0, 200, 320, 75)];
maScrollView.backgroundColor = [UIColor yellowColor];
maScrollView.contentSize = CGSizeMake(1000, 75);
[self.view addSubview:maScrollView];
// Placer un Label pour visualiser le défilement
unLabel =
[[UILabel alloc] initWithFrame:CGRectMake(300, 10, 75, 50)];
unLabel.text = @"Le texte";
[maScrollView addSubview:unLabel];
// …
}
Lorsqu’on veut avertir l’utilisateur et créer une alerte se présentant à l’écran, on peut utiliser les fenêtres d’alerte (UIAlertViews
) ou bien les feuilles d’action (UIActionSheet
).
La classe UIAlertView
alloue la fenêtre d’alerte, qui sera ensuite présentée à l’écran en attendant que l’utilisateur la quitte.
Pour avoir un contrôle lors de la réponse à l’AlertView, on doit implémenter le protocole UIAlertViewDelegate
.
La méthode alertView:clickedButtonAtIndex:
de ce délégué est appelée quand l’utilisateur a sélectionné l’une des options de l’AlertView.
Figure 9–9
Dans l’exemple qui suit, l’AlertView est déclenchée par un bouton dans la vue présentée à l’utilisateur.
Exemple d’utilisation d’une AlertView dans le fichier .h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UIAlertViewDelegate> {
UIButton *boutonAlerte;
}
@property(strong,nonatomic) IBOutlet UIButton *boutonAlerte;
// Action
- (IBAction) clicAlerte:(id)sender
@end
Exemple d’utilisation d’une AlertView dans le fichier .m
#pragma mark - Méthode delegate pour les alertviews
- (void) alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex
{
// 0 = OK, 1 = option 1, 2 = option 2
NSLog(@"%lu", (unsigned long)buttonIndex);
}
#pragma mark - Propriétés
@synthesize boutonAlerte;
#pragma mark - Mes Méthodes
// Action
- (IBAction) clicAlerte:(id)sender {
UIAlertView *alertView =
[[UIAlertView alloc] initWithTitle:@"Le titre"
message:@"Le corps du message"
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:@"Option1", @"Option 2", nil];
[alertView show];
}
Il est possible d’afficher des fenêtres d’alertes comprenant un champ de texte pour la saisie d’un nom par exemple, ou d’un mot de passe en mode sécurisé, ou bien encore d’une ligne pour le login et une autre pour le mot de passe.
On utilise pour cela la propriété alertViewStyle
de l’objet de type UIAlertView
.
La feuille d’action, de classe UIActionSheet
alloue une vue d’alerte, qui sera ensuite présentée à l’écran par le bas de l’écran en attendant que l’utilisateur la quitte.
Sur un iPad, la feuille d’action apparaîtra au centre de l’écran, ou bien sera positionnée arbitrairement à l’écran ou encore pourra apparaître sous un bouton se trouvant dans une barre de navigation (UIBarButton
).
Pour avoir un contrôle lors de la réponse à l’ActionSheet, on doit implémenter le protocole UIActionSheetDelegate
.
La méthode actionSheet:clickedButtonAtIndex:
de ce délégué est appelée quand l’utilisateur a sélectionné l’une des options de l’ActionSheet.
Dans l’exemple qui suit, l’ActionSheet est déclenchée par un bouton dans la vue présentée à l’utilisateur.
Figure 9–10 Exemple de feuille d’action
Exemple d’utilisation d’une ActionSheet dans le fichier .h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UIActionSheetDelegate> {
UIButton *boutonAction;
}
@property(strong,nonatomic) IBOutlet UIButton *boutonAction;
// Action
- (IBAction) clicAction:(id)sender;
@end
Exemple d’utilisation d’une ActionSheet dans le fichier .m
#pragma mark - Méthode delegate pour les actionsheets
- (void) actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex
{
// 0 = Annuler, 1 = Supprimer, 2 = option 1, 3 = option 2
NSLog(@"%lu", (unsigned long)buttonIndex);
}
#pragma mark - Propriétés
@synthesize boutonAction;
#pragma mark - Mes Méthodes
// Action
- (IBAction) clicAction:(id)sender {
UIActionSheet *actionSheet =
[[UIActionSheet alloc] initWithTitle:@"Le titre"
delegate:self
cancelButtonTitle:@"Annuler"
destructiveButtonTitle:@"Supprimer"
otherButtonTitles:@"Option 1",
@"Option 2",
nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
[actionSheet showInView:self.view];
}
L’affichage d’une feuille d’action sur un iPad à des coordonnées arbitraires se fait à l’aide du code suivant :
Exemple de positionnement arbitraire d’une UIActionSheet
[actionSheet showFromRect:CGRectMake(40, 20, 300, 400)
inView:self.view
animated:YES];
Et pour visualiser une feuille d’action directement sous un bouton de la barre de navigation :
Exemple de positionnement sous un bouton de navigation d’une UIActionSheet
[actionSheet showFromBarButtonItem:boutonMenu
animated:YES];
On peut utiliser la classe UIStepper
qui fait progresser une valeur, tout en fixant un minimum, un maximum et un pas de progression.
Figure 9–11 Exemple de compteur
Cette classe, facile à mettre en œuvre, fait avancer une jauge ou tout élément possédant une valeur numérique susceptible d’être modifiée (niveau de contraste, couleur, etc.).
Exemple d’utilisation d’un stepper dans le fichier .h
#import <UIKit/UIKit.h>
@interface ViewController1_iPhone : UIViewController {
UIStepper *leStepper;
UILabel *leLabel ;
}
@property (nonatomic,strong) IBOutlet UIStepper *leStepper;
@property (nonatomic,strong) IBOutlet UILabel *leLabel ;
// Actions
- (IBAction) stepperAction:(id)sender;
@end
Exemple d’utilisation d’un stepper dans le fichier .m
#import "ViewController1_iPhone.h"
#import "ViewController3_iPhone.h"
@implementation ViewController1_iPhone
#pragma mark - Propriétés
@synthesize leStepper;
@synthesize leLabel;
#pragma mark - Mes Méthodes
- (IBAction) stepperAction:(id)sender {
self.leLabel.text =
[NSString stringWithFormat:@"%.2f", self.leStepper.value];
}
- (void) viewDidLoad
{
[super viewDidLoad];
// Initialisation du stepper
self.leStepper.minimumValue = 10.0f;
self.leStepper.maximumValue = 60.0f;
self.leStepper.value = 10.0f; // Valeur initiale
self.leStepper.stepValue = 5.0f; // Progression de 5 en 5
self.leStepper.continuous = YES;
}
La classe UIWebView
s’appuie sur le moteur de rendu de Safari (WebKit) pour afficher tout contenu pris en charge directement dans votre application (HTML, PDF, images, etc.).
Elle peut charger ces contenus depuis une URL externe, depuis une chaîne de caractères de votre code ou directement depuis le bundle de votre application.
Exemple d’utilisation de la classe UIWebView
UIWebView *webView =
[[UIWebView alloc] initWithFrame:CGRectMake(0,0,320,460)];
// Chargement d’une URL réseau
[webView loadRequest:
[NSURLRequest requestWithURL:[NSURL
urlWithString:@"http://www.google.fr"]]];
// Ou chargement d’un contenu statique
[webView loadHTMLString:@"Hello <b>World</b>" baseURL:@""];
Il est également possible de définir un délégué pour que votre contrôleur soit notifié lorsque l’utilisateur navigue dans les liens (voir à ce sujet la documentation de UIWebViewDelegate
).
Toutes les vues sont aplaties et dessinées dans une zone de dessin CALayer
, issue du framework CoreAnimation
. Il est ainsi possible de mettre en place très facilement des animations.
Pour cela, on crée un bloc d’animation dans lequel on change les propriétés qui doivent varier pendant l’animation, puis on demande au système de lancer l’animation.
Exemple d’animation d’une vue
- (void) loadView {
UIView *myView =
[[UIView alloc] initWithFrame:CGRectMake(0, 20, 320, 460)];
myView.backgroundColor = [UIColor redColor];
self.view = myView;
UILabel *label =
[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
label.text = @"Un texte qui bouge";
self.movingLabel = label;
[self.view addSubview:self.movingLabel];
}
- (void) viewDidAppear:(BOOL)animated
{
[UIView beginAnimations:@"movingLabel" context:nil];
[UIView setAnimationDuration:10.0];
self.movingLabel.frame = CGRectMake(0, 440, 320, 20);
[UIView commitAnimations];
}
Cette technique peut être utilisée pour animer la plupart des propriétés d’une vue : sa taille, son opacité, sa couleur, etc. Durant l’animation, votre application continue à s’exécuter et l’utilisateur peut toujours interagir avec elle.
On peut par exemple faire pivoter ou modifier l’échelle d’une vue en utilisant la propriété transform
des vues.
- (IBAction) jeBouge:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
monImage.transform = CGAffineTransformMakeTranslation(50,100);
[UIView commitAnimations];
}
- (IBAction) jeGrandis:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
monImage.transform = CGAffineTransformMakeScale(2, 2);
[UIView commitAnimations];
}
- (IBAction) jeTourne:(id)sender {
// Utilisation du Framework Quartz pour faire un tour de 360°
// 1 seul tour pendant 6 secondes
CABasicAnimation *fullRotation;
fullRotation =
[CABasicAnimation animationWithKeyPath:@"transform.rotation"];
fullRotation.fromValue = [NSNumber numberWithFloat:0];
fullRotation.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
fullRotation.duration = 6;
fullRotation.repeatCount = 1;
}
- (IBAction) jeRedeviensCommeAvant:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
monImage.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
- (IBAction) jeMeTransforme:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
CGAffineTransform rotate = CGAffineTransformMakeRotation(0.78);
CGAffineTransform translate =
CGAffineTransformMakeTranslation(100,75);
CGAffineTransform grow = CGAffineTransformMakeScale(2, 2);
self.monImage.transform =
CGAffineTransformConcat(
CGAffineTransformConcat(translate, rotate),
grow);
[UIView commitAnimations];
}
Dans les fonctions présentées ici, déclenchées par de simples boutons, on trouve :
Fonction | Description |
JeBouge |
Cette fonction effectue une translation de la vue. |
JeGrandis |
Cette fonction change l’échelle d’un objet. Notez qu’il est possible de changer l’échelle de la largeur et de la hauteur indépendamment l’une de l’autre. |
JeTourne |
Ce cas est particulier, on devrait procéder comme avec les deux cas précédents, mais l’animation va prendre le chemin le plus court. Ainsi, une rotation de 350° correspond à une rotation antihoraire de 10°. Pour cela, on utilise le framework Quartz qui est de plus bas niveau et qui permet d’effectuer une rotation complète. |
JeRedeviensCommeAvant |
La fonction identité ramène la vue à sa position initiale. |
JeMeTransforme |
Ici, on peut concaténer plusieurs animations. La fonction de concaténation ne prenant que 2 arguments, on doit imbriquer les fonctions entre elles. |
L’iOS sait adapter la langue de l’application en fonction de l’option Général > International > Langue choisie dans ses Réglages par l’utilisateur. Les applications vont alors puiser les chaînes de caractères correspondant au choix actuel.
Pour détecter la langue en cours dans son propre code :
// Récupération de la langue de l’appareil
NSUserDefaults *defaults =
[NSUserDefaults standardUserDefaults];
// Toutes les langues de l’appareil
NSArray *langues = [defaults objectForKey:@"AppleLanguages"];
// Langue en cours
NSString *langueCourante = [langues objectAtIndex:0];
Pour créer un fichier de localisation qui contiendra les chaînes de caractères dans les langues appropriées, en français et en anglais par exemple, on effectue les opérations suivantes.
1 Créer un fichier vide dans le groupe Supporting Files
: New File > Resource > Strings et nommer le fichier Localizable.strings
.
2 Sélectionner le fichier et choisir en haut à droite dans la partie Utilities le File Inspector.
Figure 9–12 Localisation d’un fichier sous Xcode
3 Dans la rubrique Localization, cliquer sur le bouton intitulé Make Localized afin d’ajouter la localisation pour ce fichier dans votre applicatif. Choisir la langue proposée (par exemple English). Puis, toujours dans le File Inspector, cliquer sur le petit + pour ajouter de nouvelles langues.
Cela a pour effet de créer deux fichiers dans votre projet : un fichier Localizable.strings (English)
et un fichier Localizable.strings (French).
Ces fichiers sont en réalité placés dans des dossiers Mac OS X fr.lproj
et en.lproj
.
Figure 9–13 Localisation d’un fichier sous Xcode (2 langues)
Dans le fichier Localizable.strings (English),
on place les informations suivantes :
"Bonjour" = "Hello";
"Langue" = "Language";
Et dans le fichier Localizable.strings (French),
on place les informations suivantes :
"Bonjour" = "Bonjour";
"Langue" = "Langue";
On fait apparaître à gauche du signe =
une étiquette qui sera appelée dans le code et, à sa droite, la chaîne de caractères à utiliser.
Dans le code, la méthode NSLocalizedString(@"label",@"commentaire")
est appelée, qui remplace le texte de l’étiquette par le texte du fichier Localizable.strings
correspondant.
self.unLabel.text = NSLocalizedString(@"Bonjour", @"");
Il est possible également de localiser l’aspect graphique du storyboard en fonction du pays.
On sélectionne le storyboard et, comme pour le fichier Localizable.strings
, on choisit à droite la liste des langues prises en charge. Un petit triangle apparaît alors à gauche du fichier storyboard dans la partie navigation. On peut alors disposer les objets graphiques différemment selon la langue choisie par l’utilisateur et, éventuellement, mettre son texte en dur dans le graphique – bien que cela soit déconseillé.
La figure 9-12 montre le résultat obtenu en français.
Après avoir changé la langue de l’appareil en anglais, on obtient le résultat de la figure 9-13.
Figure 9–14 Localisation de votre application en français
Figure 9–15 Localisation de votre application en anglais
Ce chapitre nous a permis de découvrir les vues, qui sont les éléments avec lesquels vous composerez toutes les interfaces de votre application. Vous avez appris à les créer, à les animer et à les internationaliser.
Il y a bien d’autres vues standards fournies par UIKit
et de nombreuses possibilités de les adapter à votre besoin. Vous les découvrirez en étudiant les applications disponibles sur l’App Store et en parcourant la documentation.
Le prochain chapitre traite des PickerViews, ce qui nous permettra de couvrir en détail la notion de delegate (délégué) et de data source.
Propriété de Marie Richie <FB1245387-C111754-prod@customers.feedbooks.com>