9

Développer et animer les vues

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.

Comprendre les vues

Une vue est un objet qui dérive de la classe UIView. Elle représente une sous-partie de sa vue parente.

Coordonnées des vues

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.

Centre et limites d’une vue

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.

image

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.

Frame d’une vue

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);

image

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.

Hiérarchie des vues

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.

image

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.

Positionnement des sous-vues et redimensionnement automatique des vues

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.

Tableau 9–1 Valeurs pour autoresizingMask
Valeur Comportement
UIAutoresizeMask​FlexibleHeight
UIAutoresizeMask​FlexibleWidth
Indiquent que la hauteur et/ou la largeur de la vue peuvent être ajustées.
UIAutoresize​MaskFlexibleMarginLeft
UIAutoresizeMask​FlexibleMarginRight
UIAutoresizeMask​FlexibleMarginTop
UIAutoresizeMask​FlexibleMarginBottom
Indiquent que certaines des marges de la vue peuvent être agrandies ou rétrécies.
Disposition automatique – Auto Layout

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.

image

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.

image

Figure 9–5 Modification d’une contrainte d’espacement et résultat dans le simulateur

NOTE Choix de AutoLayout

Le choix AutoLayout ou non se détermine de façon globale dans le StoryBoard. Pour cela, aller dans le File Inspector et cocher ou non la case intitulée Use AutoLayout.

Les vues élémentaires de UIKit

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 ;

Les labels pour afficher du texte

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.

Tableau 9–2 Principales propriétés de UILabel
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.

Les vues d’images

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];

Les boutons pour déclencher des actions

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]; image

unBouton.frame = CGRectMake(20, 300, 200, 30); image

[unBouton setTitle:@"Clic" forState:UIControlStateNormal]; image

[unBouton setTitle:@"Pressé !" forState:UIControlStateHighlighted]; image

[unBouton setTitleColor:[UIColor blackColor]

forState:UIControlStateNormal]; image

[unBouton setOpaque:NO];

[unBouton setAlpha:1];

[unBouton addTarget:self

action:@selector(actionDuBouton:)

forControlEvents:UIControlEventTouchUpInside];image

[self.view addSubview:unBouton]; image

}

image Le bouton est d’abord créé.

image Puis il est placé à l’écran dans un cadre (frame).

image Ensuite, un titre est associé au bouton en fonction de son état (au départ).

image Puis lorsqu’il est pressé.

image 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.

image Le bouton est associé à une méthode lorsqu’il est pressé (TouchUpInside).

image Puis le bouton est placé dans la vue courante par l’appel à la méthode addSubview:.

Les zones de texte

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

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.

image

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

Les commutateurs (UISwitch) proposent à l’utilisateur un choix de type I/O (Yes/No). On ne peut pas changer le label d’un commutateur.

image

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"]];

}

Les scrollviews

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.

image

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];

// …

}

Alertes et feuilles d’action

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.

image

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.

image

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];

Utilisation d’un compteur

On peut utiliser la classe UIStepper qui fait progresser une valeur, tout en fixant un minimum, un maximum et un pas de progression.

image

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;

}

Affichage de contenus web dans l’application

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).

Animation des vues

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 { image

[UIView beginAnimations:nil context:nil];

[UIView setAnimationDuration:1.5];

monImage.transform = CGAffineTransformMakeTranslation(50,100);

[UIView commitAnimations];

}

- (IBAction) jeGrandis:(id)sender { image

[UIView beginAnimations:nil context:nil];

[UIView setAnimationDuration:1.5];

monImage.transform = CGAffineTransformMakeScale(2, 2);

[UIView commitAnimations];

}

- (IBAction) jeTourne:(id)sender { image

// 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 { image

[UIView beginAnimations:nil context:nil];

[UIView setAnimationDuration:1.5];

monImage.transform = CGAffineTransformIdentity;

[UIView commitAnimations];

}

- (IBAction) jeMeTransforme:(id)sender { image

[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 image Cette fonction effectue une translation de la vue.
JeGrandis image 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 image 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 image La fonction identité ramène la vue à sa position initiale.
JeMeTransforme image Ici, on peut concaténer plusieurs animations. La fonction de concaténation ne prenant que 2 arguments, on doit imbriquer les fonctions entre elles.

Internationalisation des vues

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];

Localisation des chaînes de caractères

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.

image

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.

image

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", @"");

Localisation du storyboard

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.

image

Figure 9–14 Localisation de votre application en français

image

Figure 9–15 Localisation de votre application en anglais

Conclusion

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>