Comme leur nom le laisse supposer, les contrôles d'action sont utilisés pour effectuer des actions lorsque l'utilisateur interagit avec l'écran de son device.
Dans cette section, vous allez apprendre à relier un contrôle d'action (bouton de commande, slider, zone de texte modifiable, etc.) au code de l'application afin de gérer un événement utilisateur. Si nécessaire, vous pourrez même créer plusieurs liaisons pour gérer plusieurs types d'actions. La technique est la même, seul le code à exécuter change.
C'est (entre autres) en choisissant soigneusement les contrôles d'action utilisés qu’une application sera intuitive, agréable et facile à utiliser. Tournez vites les pages et découvrez les contrôles d’action utilisables sur un device iOS 5.
Boutons
Les boutons sont les contrôles d'action de base. Leur apparence peut être personnalisée en utilisant Interface Builder ou des instructions Objective-C. Vous pouvez par exemple choisir la forme, le texte, l'image, la couleur d'arrière-plan et encore beaucoup d'autres caractéristiques.
Interface Builder donne accès à cinq types de boutons prédéfinis, comme le montre la figure suivante.

Pour transformer un bouton par défaut (Rounded Rect
) en un bouton prédéfini, il suffit de faire votre choix dans la liste déroulante Type
, comme indiqué à la figure suivante.

Il est également possible d'ajouter une image à un bouton Rounded Rect
: insérez une image de petite taille dans les ressources de l'application et sélectionnez-la dans la propriété Image
du bouton. Si nécessaire, complétez cette image avec un texte, comme à la figure suivante.

Enfin, il est également possible de créer un bouton en utilisant du code Objective-C :
UIButton *monBouton = [UIButton buttonWithType:UIButtonTypeInfoDark ];
[monBouton setCenter:CGPointMake(100.0f, 100.0f)];
[self.view addSubview: monBouton];
La première instruction définit l'objet monBouton
, le rattache à la classe UIButton
et définit son type UIButtonTypeInfoDark
.
La deuxième instruction définit les coordonnées du centre du bouton. Le premier nombre correspond à l'abscisse et le deuxième à l'ordonnée, par rapport au coin supérieur gauche de l'écran.
Enfin, la troisième instruction ajoute le bouton à la vue courante.
Si le bouton est de type Rounded Rect
, vous pouvez également définir sa taille et le texte qui y est affiché :
UIButton *monBouton = [UIButton buttonWithType:UIButtonTypeRoundedRect ];
[monBouton setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 20.0f)];
[monBouton setTitle: @"Mon bouton" forState: UIControlStateNormal];
[self.view addSubview: monBouton];
La première instruction définit l'objet monBouton
, le rattache à la classe UIButton
et définit son type UIButtonTypeInfoDark
.
La deuxième instruction définit la position (les deux premiers paramètres) et les dimensions (les deux derniers paramètres) du bouton.
La troisième instruction définit le texte affiché dans le bouton.
Enfin, la quatrième instruction ajoute le bouton à la vue courante.
Les boutons relèvent de la classe UIButton
. L'événement déclencheur par défaut est Touch Up Inside
; en d'autres termes, lorsqu'un doigt est enlevé du bouton. Si nécessaire, il est possible d'utiliser plusieurs autres déclencheurs. Par exemple Touch Down
(lorsqu'un doigt est posé sur le bouton), Value Changed
(modification du texte du bouton) ou encore Touch Drag Inside
(appui sur le bouton et déplacement du doigt).
J'ai défini une action et une méthode événementielle pour mon bouton, mais lorsque j'appuie dessus, rien ne se passe. Est-ce que j'aurais raté quelque chose ?
Il y a de grandes chances pour que vous n'ayez pas relié le bouton et le code.
Contrôle-glissez-déposez le bouton de la zone d'édition sur le fichier d'en-têtes, juste au-dessus du @end
. Au relâchement du bouton gauche de la souris, sélectionnez Action
dans la liste Connection
, donnez un nom à l'action et cliquez sur Connect
.
Segmented Control
Les contrôles Segmented Control
sont comparables à des onglets. Ils sont utilisés pour afficher ou cacher certains éléments en fonction de l'onglet (ou plutôt du « segment » dans le jargon Xcode) sélectionné. Ils sont attachés à la classe UISegmentedControl
.
Supposons par exemple que vous ayez attaché plusieurs images à votre projet. En utilisant un Segmented Control
, vous pouvez afficher une image pour chaque onglet. Nous allons mettre cela en pratique.
Définissez une nouvelle application basée sur le modèle Single View Application
et donnez-lui le nom « onglets ». En utilisant Interface Builder, ajoutez au fichier MainStoryboard.storyboard
un contrôle Segmented Control
, un contrôle Image View
et un contrôle Label
. Positionnez et redimensionnez ces contrôles pour obtenir quelque chose comme la figure suivante.

Contrôle-glissez-déposez les contrôles de la zone d'édition sur le code du fichier d'en-têtes ViewController.h
et définissez les connexions suivantes :
Contrôle | Type de liaison | Nom |
---|---|---|
Segmented Control | Outlet | onglets |
Segmented Control | Action | ongletChange |
Image View | Outlet | image |
Label | Outlet | sousTitre |
Le fichier ViewController.h
doit maintenant contenir les instructions suivantes :
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UISegmentedControl *onglets;
(IBAction)ongletChange:(id)sender;
@property (weak, nonatomic) IBOutlet UIImageView *image;
@property (weak, nonatomic) IBOutlet UILabel *sousTitre;
@end
Cette première étape effectuée, vous allez ajouter un onglet au Segmented Control
et redéfinir le nom des trois onglets. Commencez par sélectionner le Segmented Control
dans le canevas, cliquez sur l'icône Show the Attributes inspector
dans la partie supérieure du volet des utilitaires. Inscrivez « 3 » dans la propriété Segments
et appuyez sur la touche Entrée de votre clavier. Le contrôle comporte maintenant trois onglets.
Double-cliquez successivement sur chaque onglet dans la zone d'édition et renommez-les « Premier », « Deuxième » et « Troisième ». Si les onglets se recouvrent l'un l'autre, redimensionnez le Segmented Control
pour arranger les choses. L'interface doit maintenant ressembler à la figure suivante.

Définissez un dossier « Resources » et ajoutez trois images de 320x480 pixels dans ce dossier. Si cette manipulation vous échappe, reportez-vous à la section "Afficher une image" du chapitre 2 de la partie III. À la figure suivante se trouvent les trois images que j'ai utilisées. Elles proviennent de la bibliothèque de cliparts de Microsoft Office.



Il est temps d'écrire quelques lignes de code. Aucune image n'ayant été affectée au contrôle Image View
, ni aucun texte au contrôle Label
, nous allons le faire via la méthode viewDidLoad
.
Cliquez sur ViewController.m
dans le volet de navigation et modifiez la méthode viewDidLoad
comme suit :
(void)viewDidLoad
{
[super viewDidLoad];
UIImage *imageCourante = [UIImage imageNamed: @"cheval.jpg"];
[image setImage: imageCourante];
sousTitre.text = @"Un cheval et sa cavalière";
}
La ligne 4 définit l'objet UIImage imageCourante
(UIImage *imageCourante
) et lui affecte l'image « cheval.jpg » qui se trouve dans les ressources de l'application (= [UIImage imageNamed: @"cheval.jpg"]
):
UIImage *imageCourante = [UIImage imageNamed: @"cheval.jpg"];
La ligne 5 affecte l'objet imageCourante
au contrôle imageView image
, et provoque son affichage :
[image setImage: imageCourante];
Enfin, la ligne 6 affiche un texte dans le Label
:
sousTitre.text = @"Un cheval et sa cavalière";
Pour terminer l'application, il ne reste plus qu'à réagir aux changements d'onglets en affichant les images et le texte correspondants. Déplacez-vous dans la partie inférieure du code et complétez la méthode ongletChange
comme suit :
(IBAction)ongletChange:(id)sender {
if (onglets.selectedSegmentIndex == 0)
{
UIImage *imageCourante = [UIImage imageNamed: @"cheval.jpg"];
[image setImage: imageCourante];
sousTitre.text = @"Un cheval et sa cavalière";
}
if (onglets.selectedSegmentIndex == 1)
{
UIImage *imageCourante = [UIImage imageNamed: @"chien.jpg"];
[image setImage: imageCourante];
sousTitre.text = @"Un chien";
}
if (onglets.selectedSegmentIndex == 2)
{
UIImage *imageCourante = [UIImage imageNamed: @"chat.jpg"];
[image setImage: imageCourante];
sousTitre.text = @"Un chat";
}
}
Cette méthode est appelée chaque fois que l'utilisateur change d'onglet. Pour savoir quel onglet a été sélectionné, il suffit de lire la valeur stockée dans la propriété selectedSegmentIndex
du contrôle Segmented Index
(ici onglets
). Cette propriété vaut 0
lorsque le premier onglet a été sélectionné, 1
lorsque le deuxième onglet a été sélectionné, 2
lorsque le troisième onglet a été sélectionné, et ainsi de suite.
Comme vous pouvez le remarquer, la méthode ongletChange
est composée de trois blocs d'instructions à peu près similaires. Vous pouvez exécuter le projet.
À la figure suivante se trouve le résultat que j'ai obtenu.

Zones de texte
Les contrôles Text Field
sont des zones de texte monolignes librement éditables par l'utilisateur. Lorsque l'utilisateur clique dans une zone de texte, le clavier intégré s'affiche dans la partie inférieure de l'écran, comme à la figure suivante.

Lorsque l'utilisateur a terminé la saisie, il appuie sur la touche Return
du clavier intégré. Ce dernier doit alors disparaître. Pour cela, plusieurs actions sont nécessaires.
Dans le fichier .h
Supposons que votre application soit basée sur le modèle Single View Application
, qu'elle ait pour nom tf
(comme Text Field
) et que son canevas contienne un contrôle Text Field
. Vous allez ajouter la déclaration qui apparaît ligne 5 dans le fichier ViewController.h
:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
(IBAction)saisieReturn :(id)sender;
@end
Dans le fichier .m
Définissez le code relatif à la méthode saisieReturn
dans le fichier ViewController.m
:
(IBAction)saisieReturn :(id)sender
{
[sender resignFirstResponder];
}
Le message [sender resignFirstResponder];
indique à son destinataire qu'il n'est plus le premier répondant. Si cette méthode est reliée à l'événement Did End on Exit
de la zone de texte, le clavier disparaîtra, puisque la zone de texte n'aura plus le focus. Dans la prochaine étape, nous allons donc relier l'événement Did End on Exit
et la méthode saisieReturn
.
Dans Interface Builder
Comme à la figure suivante :
cliquez sur
MainStoryboard.storyboard
dans le volet de navigation (1) ;cliquez sur la zone de texte dans la vue (2) ;
affichez le volet des utilitaires en cliquant sur
Hide or Show the Utilities
(3) ;affichez les connexions en cliquant sur
Show the Connections Inspector
(4) ;repérez le bouton radio à droite de
Did End On Exit
, pointez-le, maintenez le bouton gauche de la souris enfoncé et déplacez la souris sur l'icôneView Controller
(5) ;au relâchement du bouton gauche de la souris, sélectionnez
saisieReturn
dans le menu (6).

Pour récupérer le contenu d'une zone de texte, il suffit d'utiliser sa propriété text
. Nous allons illustrer cette propriété en définissant une mini-application composée d'une zone de texte et d'un label, comme à la figure suivante.

Pour obtenir ce résultat, commencez par définir une application basée sur le modèle Single View Application
, ajoutez un contrôle Text Field
et un contrôle Label
au canevas.
L'application n'a pas encore l'apparence souhaitée. Vous devez modifier deux paramètres dans l'inspecteur des attributs :
cliquez sur le contrôle
Text Field
et écrivez «-
-
-
Entrez du texte ici-
-
-
» dans le paramètrePlaceholder
;cliquez sur le contrôle
Label
et tapez « Aucun texte n'a été entré » dans le paramètreText
.
Pour les étourdis, je rappelle que l'inspecteur des attributs est affiché en cliquant respectivement sur l'icône Hide or show the Utilities
et Show the Attributes inspector
. Il suffit alors de modifier l'attribut souhaité .
Vous allez maintenant relier ces deux contrôles au code de l'application :
Cliquez sur l'icône
Show the Assistant editor
dans la barre d'outils de Xcode.Contrôle-glissez-déposez le contrôle
Text Field
du canevas dans le code source du fichierViewController.h
et créez l'outletsaisie
.Contrôle-glissez-déposez le contrôle
Label
du canevas dans le code source du fichierViewController.h
et créez l'outletstatus
.
Après ces manipulations, le fichier ViewController.h
devrait contenir les instructions suivantes :
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
(IBAction)saisieReturn :(id)sender;
@property (weak, nonatomic) IBOutlet UITextField *saisie;
@property (weak, nonatomic) IBOutlet UILabel *status;
@end
Nous allons supposer que l'effacement du clavier a été mis en place lorsque l'utilisateur appuie sur la touche Return
, comme indiqué précédemment. Une ligne supplémentaire dans la méthode saisieReturn
va suffire pour afficher le contenu de la zone de texte dans le Label
(ici la ligne 3) :
(IBAction)saisieReturn :(id)sender
{
status.text = [NSString stringWithFormat: @"%@%@", @"Vous avez tapé : ",saisie.text];
[sender resignFirstResponder];
}
La propriété text
du contrôle Label
(status.text
) est initialisée avec l'objet NSString
retourné par le message qui suit le signe « = ». Cet objet est constitué par la concaténation (c'est-à-dire l'ajout) de deux textes (stringWithFormat: @"%@%@"
) : la chaîne « Vous avez tapé » (@"Vous avez tapé : "
) et le contenu du contrôle Text Field
(saisie.text
).
Curseurs
Les contrôles Slider
(figure suivante) sont des curseurs horizontaux dont la position est ajustable par l'utilisateur. Vous les utiliserez pour faciliter la sélection de valeurs dans des plages.

Ces contrôles relèvent de la classe UISlider
. Il est possible de les personnaliser dans Interface Builder en définissant :
une image pour représenter la valeur minimale et une autre pour représenter la valeur maximale ;
les valeurs minimales et maximales ;
la valeur par défaut au lancement de l'application.
La position du curseur est accessible à tout moment dans la propriété value
.
Pour illustrer le fonctionnement de ce contrôle, nous allons créer une mini-application qui affiche dans un Label
la position d'un Slider
, et ce à chaque modification du curseur par l'utilisateur.
Définissez un nouveau projet en utilisant le modèle Single View Application
et donnez-lui le nom « slider ». Ajoutez un Slider
et un Label
au canevas. Reliez le Label
au fichier .h
; pour cela, effectuez un contrôle-glisser-déposer du Label
dans le fichier .h
et donnez le nom status
à l'outlet ainsi créé.
Reliez le Slider
au fichier .h
. Pour cela, effectuez un contrôle-glisser-déposer du Slider
dans le fichier .h
. Au relâchement du bouton gauche de la souris, sélectionnez Action
dans la liste Connection
, choisissez Value Changed
dans la liste Event
et tapez « sl » dans la zone de texte Name
.
Le fichier .h
doit maintenant ressembler à ceci :
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *status;
(IBAction)sl:(id)sender;
@end
Pour compléter ces définitions, vous devez définir quelques lignes de code dans la méthode sl
qui, rappelons-le, réagit à l'événement Value Changed
du Slider
:
(IBAction)sl:(id)sender {
UISlider *slider = (UISlider *)sender;
status.text = [NSString stringWithFormat:@"%1.2f", slider.value];
}
La ligne 2 définit l'objet slider
de type UISlider
et le relie au Slider
qui est à l'origine de l'événement.
La ligne 3 convertit la propriété value
du Slider
(slider.value
) en un objet NSString
(NSString stringWithFormat:@"%1.2f", …
). L'objet ainsi obtenu est placé dans la propriété text
du Label status
(status.text = …
), ce qui provoque l'affichage de la valeur du curseur dans le label.
Interrupteurs
Vous utiliserez un contrôle Switch
chaque fois qu'il est nécessaire de mettre en place un interrupteur marche/arrêt, comme celui utilisé dans les réglages du device pour le mode avion (figure suivante).

Le contrôle Switch
relève de la classe UISwitch
. La propriété booléenne on
permet de connaître son état et la méthode setOn
de le modifier. Voici la syntaxe de cette méthode :
(void)setOn:(BOOL)on animated:(BOOL)animated
Donnez la valeur :
YES
ouNO
au paramètreon
selon que vous vouliez mettre l'interrupteur surON
ou surOFF
.YES
ouNO
au paramètreanimated
selon que vous vouliez changer l'état de l'interrupteur ; c'est-à-dire avec ou sans animation.
Pour illustrer l'utilisation de ce contrôle, nous allons définir une mini-application qui affiche l'état d'un interrupteur marche/arrêt chaque fois que celui-ci change.
Définissez un nouveau projet en utilisant le modèle Single View Application
et donnez-lui le nom « switch ». Ajoutez un Switch
et un Label
au canevas.
Reliez le Label
au fichier .h
en effectuant un contrôle-glisser-déposer du Label
dans le fichier .h
et donnez le nom « status » à l'outlet ainsi créé.
Reliez le Switch
au fichier .h
en effectuant un contrôle-glisser-déposer du Switch
dans le fichier .h
. Au relâchement du bouton gauche de la souris, sélectionnez Action
dans la liste Connection
, choisissez Value Changed
dans la liste Event
et tapez « sw » dans la zone de texte Name
.
Le fichier .h
doit maintenant ressembler à ceci :
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *status;
(IBAction)sw:(id)sender;
@end
Pour compléter ces définitions, vous devez définir quelques lignes de code dans la méthode sw
qui, rappelons-le, réagit à l'événement Value Changed
du Switch
. Cliquez sur ViewController.m
dans le volet de navigation puis modifiez la méthode sw
comme suit :
(IBAction)sw:(id)sender {
UISwitch *uis = (UISwitch *) sender;
if (uis.on == TRUE)
status.text = @"Le switch est sur ON";
else
status.text = @"Le switch est sur OFF";
}
La deuxième ligne définit l'objet uis
de classe UISwitch
et le relie au switch
qui est à l'origine de l'événement.
La ligne suivante teste la valeur de la propriété on
du switch
. Si cette propriété vaut TRUE
, cela signifie que l'interrupteur vient d'être initialisé à ON
. Le texte « Le switch est sur ON » est alors affiché dans le label :
status.text = @"Le switch est sur ON";
Dans le cas contraire, cela signifie que l'interrupteur vient d'être initialisé à OFF
. Le texte « Le switch est sur OFF » est alors affiché dans le label :
else
status.text = @"Le switch est sur OFF";
Contrôles de page
Les contrôles Page Control
sont utilisés dans une vue qui comporte plusieurs pages. Ils permettent à l'utilisateur :
de savoir où se situe la page courante dans l'ensemble des pages ;
de se déplacer dans l'ensemble des pages.
Ces contrôles relèvent de la classe UIPageControl
. Pour vous montrer comment les utiliser, nous allons développer une application dans laquelle un contrôle Scroll View
contient des zones colorées mises bout à bout. Comme vous pouvez le voir sur l'image suivante, le Scroll View
est bien plus large que l'écran de l'iPhone : il comporte cinq zones colorées de la même taille que l'écran.

Définissez une nouvelle application basée sur le modèle Single View Application
et donnez-lui le nom « page ». En utilisant Interface Builder, ajoutez un contrôle Scroll View
au fichier MainStoryboard.storyboard
, et redimensionnez-le pour qu'il occupe la quasi-totalité de l'écran.
Contrôle-glissez-déposez le contrôle Scroll View
de la zone d'édition dans le code du fichier d'en-têtes ViewController.m
et définissez l'outlet sv
. Le fichier d'en-têtes doit maintenant ressembler à ceci :
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIScrollView *sv;
@end
Nous allons maintenant définir les rectangles colorés qui seront affichés dans le contrôle Scroll View
.
Pour qu'un rectangle représente une page dans le Scroll View
, il suffit de lui donner la même taille que le Scroll View
. Pour cela, nous allons utiliser la méthode viewDidLoad
.
Cliquez sur ViewController.m
dans le volet de navigation et complétez la méthode viewDidLoad
comme ceci :
(void)viewDidLoad
{
[super viewDidLoad];
NSArray *couleurs = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], [UIColor cyanColor], [UIColor yellowColor],nil];
for (int i = 0; i < couleurs.count; i++)
{
// Définition d'un rectangle
CGRect rectangle;
rectangle.origin.x = sv.frame.size.width * i;
rectangle.origin.y = 0;
rectangle.size = sv.frame.size; //Le rectangle a la même dimension que le UIScrollView
// Ajout de la vue correspondante
UIView *subview = [[UIView alloc] initWithFrame:rectangle];
subview.backgroundColor = [couleurs objectAtIndex:i];
[sv addSubview:subview];
}
sv.contentSize = CGSizeMake(sv.frame.size.width * couleurs.count, sv.frame.size.height);
}
La ligne 4 définit un objet NSArray
nommé couleurs
(NSArray *couleurs
) et l'initialise avec cinq couleurs prédéfinies.
Le bloc d'instructions suivant (lignes 5 à 17) définit les cinq rectangles et les transforme en vues du contrôle Scroll View
. Pour bien faire les choses, la boucle for
utilise le nombre de couleurs définies dans le tableau couleurs
(couleurs.count
) comme borne supérieure. Ainsi, si vous voulez définir plus ou moins de couleurs, l'application fonctionnera tout aussi bien :
for (int i = 0; i < couleurs.count; i++)
{
...
}
Les rectangles sont des objets CGRect
. La première instruction de la boucle (ligne 8) commence par définir un objet rectangle de type CGRect
:
CGRect rectangle;
Les trois instructions suivantes définissent l'origine et la taille du rectangle :
rectangle.origin.x = sv.frame.size.width * i;
rectangle.origin.y = 0;
rectangle.size = sv.frame.size;
Remarquez la façon dont est définie l'abscisse (rectangle.origin.x
) du rectangle :
rectangle.origin.x = sv.frame.size.width * i;
La propriété frame.size.width
de l'objet UIScrollView sv
donne la largeur de ce contrôle. En la multipliant par l'index de la boucle, qui vaut consécutivement 0
, 1
, 2
, 3
puis 4
, on obtient les valeurs suivantes :
Index | rectangle.origin.x |
---|---|
0 | 0 |
1 | Largeur de sv |
2 | 2 largeurs de sv |
3 | 3 largeurs de sv |
4 | 4 largeurs de sv |
Les cinq rectangles colorés seront donc placés côte à côte horizontalement.
Les instructions suivantes (lignes 14 à 16) définissent les différentes vues qui composent l'objet Scroll View
. Pour cela, un objet subview
de classe UIView
est défini (UIView *subview
) et initialisé avec le rectangle créé quelques lignes plus haut (initWithFrame:rectangle
) :
UIView *subview = [[UIView alloc] initWithFrame:rectangle];
La couleur de cet objet est alors initialisée avec la couleur définie dans l'élément d'index i
du tableau :
subview.backgroundColor = [couleurs objectAtIndex:i];
La sous-vue est enfin définie en utilisant l'objet subview
:
[sv addSubview:subview];
Vous pouvez lancer l'application et constater (oh merveille !) qu'il est possible de scroller horizontalement dans le Scroll View
.
Vous allez maintenant ajouter un contrôle Page Control
au fichier ViewController.xib
. Par défaut, le nombre de pages accessibles via un Page Control
est égal à trois. Dans notre cas, nous devons scroller à travers cinq pages. Il faut donc modifier le nombre de pages par défaut. Cliquez sur le Page Control
dans la zone d'édition, affichez le volet des attributs (si nécessaire en cliquant sur Hide or show the Utilities
puis sur Show the Attributes inspector
) et modifiez la valeur de l'attribut Pages
, comme indiqué à la figure suivante.

Définissez un outlet et une action pour le contrôle Page Control
et nommez-les (respectivement) « laPage » et « changePage ». Le fichier d'en-têtes doit maintenant ressembler à ceci :
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIScrollView *sv;
@property (weak, nonatomic) IBOutlet UIPageControl *laPage;
(IBAction)changePage:(id)sender;
@end
Pour que le Page Control
puisse être mis à jour lorsque l'utilisateur change de page en utilisant une gestuelle de glisser, il est nécessaire d'être informé de cette gestuelle. Pour cela, nous déléguerons cette tâche au Scroll View
. Il est donc nécessaire :
d'ajouter le protocole
UIScrollViewDelegate
dans le contrôleur de vue, c'est-à-dire dans le fichierViewController.h
;de connecter le
delegate
duScroll View
au contrôleur de vue.
À quoi vont servir ces deux étapes au juste ? Je ne suis pas sûr de bien comprendre.
Elles vont permettre d'écrire dans le code du contrôleur de vue (ViewController.m
) les méthodes événementielles en rapport avec le contrôle Scroll View
. En effet, en ajoutant le delegate UIScrollViewDelegate
au contrôleur de vue et en le reliant au contrôleur de vue, ce dernier sera capable de traiter les événements du contrôle Scroll View
.
La première étape se fait en spécifiant le protocole dans la déclaration de l'interface :
@interface ViewController : UIViewController <UIScrollViewDelegate>
{
...
}
La deuxième étape se fait en cliquant sur le contrôle Scroll View
dans le canevas (1), puis en glissant-déposant le cercle à droite de delegate
sur l'icône View Controller
(2), comme à la figure suivante.

Retournons au code.
Cliquez sur ViewController.m
dans le volet de navigation.
Le contrôleur de vue étant le délégué du Scroll View
, nous allons utiliser une méthode de ce dernier pour mettre à jour le Page Control
. Insérez la méthode suivante à un endroit quelconque dans le code. Par exemple juste avant la méthode viewDidLoad
:
(void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat largeurPage = sv.frame.size.width;
int page = floor((sv.contentOffset.x - largeurPage / 2) / largeurPage) + 1;
laPage.currentPage = page;
}
Cette méthode est exécutée lorsque l'utilisateur déplace horizontalement le Scroll View
.
La ligne 2 stocke la largeur d'une page (c'est-à-dire celle du Scroll View
) dans la variable CGFloat largeurPage
:
CGFloat largeurPage = sv.frame.size.width;
La ligne 3 calcule le numéro de la page affichée dans le Scroll View
. Ce numéro change lorsque la vue est décalée de plus de la moitié de l'écran (figure suivante).

Le calcul paraît complexe, mais il n'en est rien. La propriété sv.ContentOffset.x
représente le décalage de l'élément affiché dans le Scroll View
. Si on lui soustrait la moitié de la largeur de la page, et qu'on divise le résultat par la largeur de la page, on obtient :
0
lors du scroll de la page1
à la page2
1
lors du scroll de la page2
à la page3
etc.
En ajoutant 1
à cette valeur, on obtient exactement ce qui est recherché, à savoir le numéro de la page vers laquelle l'utilisateur se déplace.
Toujours dans le flou ? Passons à une application numérique. Nous allons supposer que le device utilisé est un iPhone 3G. Bien sûr, ce raisonnement fonctionne sur tous les autres devices, mais il fallait bien en choisir un pour passer à l'application numérique.
La résolution d'un iPhone 3G est de 320x480 pixels. Supposons que l'utilisateur soit en train d'effectuer une gestuelle pour passer du premier écran au deuxième (comme sur la figure précédente).
Examinons les valeurs des différents éléments contenus dans la formule floor((sv.contentOffset.x - largeurPage / 2) / largeurPage) + 1
.
L'élément | va passer de ... à ... |
---|---|
sv.contentOffset.x | 0 à 320 |
sv.contentOffset.x - largeurPage / 2 | -160 à 160 |
(sv.contentOffset.x - largeurPage / 2) / largeurPage | -0.5 à 0.5 |
floor((sv.contentOffset.x - largeurPage / 2) / largeurPage) | -1 jusqu'au milieu de l'écran, 0 après |
floor((sv.contentOffset.x - largeurPage / 2) / largeurPage) + 1 | 0 jusqu'au milieu de l'écran, 1 après |
Libre à vous de décomposer les calculs pour le passage du deuxième au troisième écran, du troisième au quatrième et du quatrième au cinquième. Vous verrez, cela fonctionne.
Si vous vous demandez comment j'ai pu trouver cette formule, eh bien, je me suis demandé quel résultat je voulais obtenir et après deux ou trois essais infructueux, je suis arrivé à définir la bonne formule. Cette approche fonctionne bien pour toutes sortes de formules, qu'elles soient plus simples ou plus complexes…
Retournons au code de l'application. Pour mettre à jour en conséquence le Page Control
, il suffit d'affecter la valeur que l'on vient de calculer à sa propriété currentPage
:
laPage.currentPage = page;
Pour terminer, nous allons compléter la méthode action changePage
pour réagir aux actions de l'utilisateur sur le Page Control
. En effet, pour le moment, ce contrôle est juste utilisé pour afficher la page active, mais pas pour changer de page. Rassurez-vous : le code sera bien plus simple que le précédent.
Localisez la méthode changePage
et complétez-la comme suit :
(IBAction)changePage:(id)sender {
CGRect frame;
frame.origin.x = sv.frame.size.width * laPage.currentPage;
frame.origin.y = 0;
frame.size = sv.frame.size;
[sv scrollRectToVisible:frame animated:YES];
}
La ligne 2 définit la variable frame
de type CGRect
. Le code se poursuit en définissant l'abscisse et l'ordonnée de l'affichage. Si vous n'avez qu'une vague idée de ce que représentent ces termes mathématiques, la figure suivante va vous rappeler de vieux souvenirs.

La ligne 3 définit le décalage en abscisse (frame.origin.x
) de l'affichage :
frame.origin.x = sv.frame.size.width * laPage.currentPage;
Ce décalage est calculé en multipliant le numéro de la page courante par la largeur d'une page.
L'ordonnée de l'affichage est toujours égale à zéro :
frame.origin.y = 0;
Et la propriété size
du rectangle est mise à jour avec les composantes x
et y
qui viennent d'être calculées :
frame.size = sv.frame.size;
Il ne reste plus qu'à mettre à jour l'affichage dans le Scroll View
en définissant le rectangle visible (scrollRectToVisible:frame
) et en demandant une animation (animated:YES
) :
[sv scrollRectToVisible:frame animated:YES];
Vous pouvez (enfin) exécuter l'application et profiter du résultat !
En résumé
Les boutons sont les contrôles d'action de base. Leur apparence peut être personnalisée en utilisant Interface Builder ou des instructions Objective-C. Vous pouvez par exemple choisir la forme, le texte, l'image, la couleur d'arrière-plan et encore beaucoup d'autres caractéristiques.
Les contrôles
Segmented Control
sont comparables à des onglets. Ils sont utilisés pour afficher ou cacher certains éléments en fonction de l'onglet (ou plutôt du « segment » dans le jargon Xcode) sélectionné. Ils sont attachés à la classeUISegmentedControl
.Les contrôles
Text Field
sont des zones de texte monolignes librement éditables par l'utilisateur. Lorsque l'utilisateur clique dans unText Field
, le clavier intégré s'affiche dans la partie inférieure de l'écran.Les contrôles
Slider
sont des curseurs horizontaux dont la position est ajustable par l'utilisateur. Vous les utiliserez pour faciliter la sélection de valeurs dans des plages.Vous utiliserez un contrôle
Switch
chaque fois qu'il est nécessaire de mettre en place un interrupteur marche/arrêt, comme celui utilisé dans les réglages du device pour le mode avion.Les contrôles
Page Control
sont utilisés dans une vue qui comporte plusieurs pages. Ils permettent à l'utilisateur de savoir où se situe la page courante dans l'ensemble des pages et de se déplacer dans l'ensemble des pages.