Skip to content

9 septembre 2010 | Rédigé par Mathieu

20

Les onglets avec UITabBarController [Tutoriel iPhone n°6] [XCode 4]

Nouveau (avril 2011) : Ce tutoriel a été mis à jour et été testé pour XCode 4.

Si UINavigationController permet d’organiser les vues de façon hiérarchique et de permettre à l’utilisateur d’obtenir des détails sur un élément de son choix, il est souvent nécessaire de proposer plusieurs fonctions ou modes de recherche de manière parallèle. Citons par exemple l’application iPod qui permet de rechercher un morceau de musique par artiste, par album, par genre, etc. Cette navigation par onglets positionnés en bas de l’écran est gérée par une classe CocoaTouch : UITabBarController. Dans ce tutoriel, vous verrez comment articuler plusieurs vues à l’aide de UITabBarController et comment vous pourrez personnaliser l’apparence de ce dernier.

Créer deux UIViews à afficher

Pour commencer, ouvrez XCode et créez un projet de type « Window Based Application ».

Nous allons maintenant créer deux vues que nous enregistrerons par la suite dans le UITabBarController. Pour créer la première vue, choisissez « New File… » dans le menu « File » de XCode, puis choisissez le type UIViewController Subclass. N’oubliez pas de cocher la case « With XIB for user interface » pour que le fichier Interface Builder soit automatiquement créé. Appelez cette classe TabLabelViewController.

Ouvrez le fichier TabLabelViewController.xib et ajoutez un UILabel au centre présentant le texte de votre choix. Sauvegarder avant de continuer.

Pour la seconde vue, je vous propose quelque chose d’un peu plus sympa qu’un bête texte : nous allons afficher un logo de votre choix. Commençons d’abord par ajouter l’image dans le projet. Pour ce faire, localisez le fichier sur votre disque dur et faîtes le glisser dans la colonne de gauche de XCode, dans le répertoire de votre projet. N’oubliez pas de cocher la case « Copy items into destination group’s folder (if needed) » dans la fenêtre qui s’ouvre, pour que l’image soit dupliquée dans votre projet (et éviter de perdre vos petits par la suite).

Créons maintenant une nouvelle classe que nous appellerons TabImageViewController. A nouveau ouvrez le fichier .xib, et faîtes-y glisser, depuis la bibliothèque, un élément Image View, il doit occuper toute la place disponible dans la vue principale.

Dans la partie supérieure de la zone de droite, choisissez, si ce n’est pas le cas l’onglet « Attributes inspector » (matérialisé par un petit curseur). Dans le champ « Image », choisissez l’image que nous avons ajoutée précédemment. Avant de sauvegarder, modifier le mode de positionnement pour trouver celui qui correspondra le mieux à votre image.

Créer l’objet UITabBarController et insérer les deux vues

Nous avons maintenant deux objets ViewController. Il s’agit de les associer à un UITabBarController et ainsi naviguer entre les deux. Pour ce faire, ouvrez le fichier appelé xxxAppDelegate.h (où « xxx » est à remplacer par le nom de votre projet). Ajoutez-y la déclaration d’un nouvel objet UITabBarController.

@interface TabBarTutorialAppDelegate : NSObject <UIApplicationDelegate> {
    UITabBarController *tabBarController;
}

Ouvrez le fichier xxxAppDelegate.m pour modifier l’implémentation. Dans d’en-tête du fichier, importez les deux vues que nous venons de créer.

#import "TabLabelViewController.h"
#import "TabImageViewController.h"

Repérez à présent la méthode - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions. Cette méthode est appelée (comme son nom l’indique) dès que l’application a fini de se charger. Pour être très complet, la classe xxxAppDelegate est une classe qui vient en soutient de chaque application. Vous avez la possibilité d’y implémenter des méthodes qui seront utiles tout au long de la vie de l’application. Une traduction possible de « Delegate » est « Représentant » ce qui correspond bien à l’usage que nous avons des AppDelegate : ce sont les représentants de l’application ; nous leur apprenons à réagir convenablement quand il arrive quelque chose à l’application (démarrage, arrêt, mise en veille ou même problème de mémoire).

Mais je m’égare et philosophe sur les AppDelegate. Repérez donc cette méthode « didFinishLaunching » qui, pour le moment se charge d’afficher une fenêtre. Nous devons faire trois choses dans cette méthode :

  1. Instancier le UITabBarController
  2. Créer un TabLabelViewController et l’enregistrer dans le UITabBarController
  3. Créer un TabImageViewController et l’enregistrer

Pour enregistrer les vues dans le UITabBarController, nous utiliserons sa propriété viewControllers qui est en fait un tableau de vues.

Voici donc le code à implémenter.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	// Override point for customization after application launch.
	// Créer un tabBarViewController
	tabBarController = [[UITabBarController alloc] init];
 
	// Créer une vue 1 et affecter
	TabLabelViewController *v1 = [[TabLabelViewController alloc] initWithNibName:@"TabLabelViewController" bundle:nil];
 
	// Créer une vue image et affecter
	TabImageViewController *v2 = [[TabImageViewController alloc] initWithNibName:@"TabImageViewController" bundle:nil];
 
	tabBarController.viewControllers = [NSArray arrayWithObjects:v1, v2, nil];
 
	[v1 release];
	[v2 release];
 
	[self.window addSubview:tabBarController.view];
	[self.window makeKeyAndVisible];
	return YES;
}

Notez qu’une fois les deux UIViewController créés et ajoutés dans le NSArray, nous leur passons un signal release : ils sont en effet retenus par le UITabBarController.

Vous pouvez compiler et faire un premier essai de votre application. Vous obtiendrez bien une barre d’onglets en bas de l’écran permettant de naviguer entre les deux vues.

Personnaliser l’apparence du UITabBarController

Il y a quand même un petit problème : les onglets sont vides ! Il devraient être associés à une image et à un intitulé, au minimum. Avant de commencer, il est nécessaire de bien comprendre le fonctionnement de UITabBarController : pour savoir ce qu’il doit afficher dans l’onglet correspondant à un ViewController, il va le lui demander ! C’est le ViewController qui définit son apparence dans la barre d’onglets. Ceci se fait à l’aide d’un objet UITabBarItem qui est enregistré dans la propriété tabBarItem du UIViewController.

Le UITabBarItem permet de préciser :

  • le titre qui s’affiche en bas
  • une image. Cette image sera au format PNG en noir et transparent. Les pixels noirs seront automatiquement colorés par iOS avec cet effet bleuté pour indiquer que l’onglet est actif. Taille 30px par 30px
  • un tag : un nombre qui pourra être affichés sous forme d’une petite pastille rouge.

Pour le TabLabelViewController, nous allons créer une image PNG de notre cru (ici un petit crayon) et choisir le titre « Label ».

Pour ce faire, créez l’image avec votre logiciel préféré (on a qu’à dire GIMP) ou téléchargez-la en faisant un clic-droit sur l’image ci-dessus, et ajoutez-la au projet en le faisant glisser vers la colonne de gauche de XCode. Ouvrez le fichier TabLabelViewController.m, repérez la méthode initWithNibName, et complétez-la avec le code suivant :

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"Label" image:[UIImage imageNamed:@"crayonnoir.png"] tag:0] autorelease];
    }
    return self;
}

Pour le TabImageViewController, encore plus rapide, nous allons utiliser un élément standard du système. Il en existe quelques un : une étoile pour les favoris, un livre ouvert pour les favoris, des utilisateurs, un loupe pour la recherche… Nous allons utiliser UITabBarSystemItemFeatured qui est représenté par deux spots vers le haut. Cette fois, même plus besoin de choisir de titre : tout est fait automatiquement (et traduit).

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.tabBarItem = [[[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:0] autorelease];
    }
    return self;
}

Attention cependant, l’usage des icônes UITabBarSystemItem est très encadré par Apple pour maintenir une cohérence de la signification de ces onglets dans tout le système. Référez vous au guide « Human Interface guidelines » pour l’utilisation de ces icônes.

Et voilà un bon aperçu de tout ce que vous pouvez faire avec UITabBarController. Une dernière chose quand même : vous pouvez ajouter autant de ViewControllers dans votre TabBar : s’il y en a trop pour tous les afficher en une seule fois, iOS proposera de lui-même un bouton « More » et permettra à l’utilisateur de paramétrer son affichage et choisir l’ordre des onglets. Vous trouverez ce fonctionnement dans l’application iPod, par exemple.

Ce tutoriel touche à sa fin, merci d’être arrivé jusqu’au bout ;-) N’hésitez pas à réagir dans les commentaires, ni à poser vos questions : nous essaierons de vous répondre et de vous aider dans votre dev. pour iPhone !

Découvrez d'autre articles de la catégorie Tutoriels iPhone

Encore un peu de lecture :

20 Commentaires Poster un commentaire
  1. 10 sept 2010

    Merci pour ce super tuto, très clair et très utile.

  2. saadibader
    10 sept 2010

    Très utile merci :p

  3. 19 sept 2010

    merci beaucoup pour ce tuto, on attend la suite avec impatience :-) !!!

  4. 24 sept 2010

    Tutorial sympa en effet … mais attention à ne pas montrer le mauvais exemple !
    Il y a des fuites mémoires dans cet exemple :( . A titre d’exemple il faut faire :

    self.tabBarItem = [[[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:0] autorelease];

    N’oublie pas de fournir le code de tout l’exemple également. Je n’ai pas vu le dealloc de ton AppDelegate mais j’espère qu’il ressemble à :

    - (void) dealloc {
    [tabBarController release];
    [window release];
    [super dealloc];
    }

    Bonne continuation !

  5. 24 sept 2010

    Merci Cyril : tu as tout à fait raison, il manquait un autorelease pour éviter que ça fuite ! C’est maintenant corrigé. Par ailleurs, un point plus complet sur la gestion mémoire est normalement prévu dans un prochain tutoriel.

  6. 24 déc 2010

    Super tutoriel, merci.

    J’ai une petite question : nous avons vu comment naviguer soit avec une UINavigationController soit avec un UITabBarController, en les instanciant dans le delegate.

    Mais comment gérer les deux à la fois comme dans l’application iPod par exemple ?

  7. 25 déc 2010

    J’ai finalement trouvé la solution :) Pour ceux que cela intéresse :

    1/ J’ai déclaré le TabLabelViewController comme « delegate » (.h) :
    @interface xxxViewController : UIViewController

    2/ Dans IB, j’y ai ajouté une NavigationBar, et relié son « delegate » au « File’s Owner »

    3/ On applique le tutoriel 5, mais dans la méthode viewDidLoad du TabLabelViewController

    Ca marche nickel !! On navigue à la fois via la TabBar, et lorsque nous sommes dans le premier onglet, on navigue dans cette vue via la NavigationBar du haut, comme dans l’app. iPod.

  8. 25 déc 2010

    @Eric : Merci d’avoir partagé ta solution ! ;)

  9. Daniel
    27 jan 2011

    @Eric : Merci pour ta solution, mais j’arrive pas a faire fonctionner chez moi… je suis nouveau dans la programmation iphone et j’ai peut-etre rate un etape??

  10. 3 fév 2011

    Magnifique tuto !

    Vraiment c’est très bien expliqué et j’ai bien fait plaisir à le suivre.

    Merci beaucoup et svp plus de tuto pour iphone, je vois assez de tuts à coté d’andro.

  11. Giiome
    13 mar 2011

    merci !!

    beau travail !

  12. Gaetan
    20 mar 2011

    Hello,

    Excellent tuto.

    Je me mets doucement au développement iPhone après plusieurs années de développement Web. J’ai juste un petit soucis :
    Tuto suivi avec XCode 4, ça change peut-être

    Dans le résultat, j’obtiens deux onglets identiques. Certes, ils dirigent bien vers la vue 1 et la vue 2, mais ils sont identique, semblable à celui que je définis dans TabLabelViewController.m.

    En gros, j’ai deux Onglets qui s’appellent Label avec sur tous les deux le crayon noir, et non pas un tab favoris à droite.
    Par contre, le tab de droite renvoie bien vers ma seconde vue, et celui de gauche vers ma première.

    Développement de l’application effectué pour iOS 4.3

  13. Gaetan
    21 mar 2011

    Reflexe de développeur, Copier Coller trop rapide !

    Je me cache, et si l’on met ensemble l’heure qu’il est et ma productivité, j’en déduis qu’il est grand temps de me coucher.

    Merci à toi pour ce super tuto !

  14. 22 mar 2011

    @Gaetan : Il faut que je reteste tous les projets avec XCode 4, à l’occasion, mais normalement il ne devrait pas y avoir de problème particulier. En tous cas merci pour tes encouragements !

  15. 24 avr 2011

    Salut tout le monde !
    Ce tutoriel a été mis à jour et testé avec XCode 4. J’en ai profité pour rajouter la possibilité de télécharger l’image du petit crayon ! Have fun !

  16. aldahi
    25 avr 2011

    Hello !
    Je suis sous Xcode 4 et cela fait 4 fois que je suis le tuto à la lettre, sans alcool ni fatigue particulière et je rencontre des difficultés : au run, sur le simulateur, à part un écran blanc, je n’avais rien.

    J’ai donc relu tout le code de AppDelegate h et m

    Dans le h, on déclare window puis on fait le property.

    @interface TabBarTutorialAppDelegate : NSObject {
    UIWindow *window;
    UITabBarController *tabBarController;
    }
    @property (nonatomic, retain) IBOutlet UIWindow *window;

    Dans le m, le synthesize existe déjà :
    @synthesize window=_window;

    Or, on utilise window quand Xcode utilise _window

    J’ai donc supprimé le « =_window » dans le synthesize, et j’ai bien mes deux vues avec le tab bar. Sauf que celui ci ne comporte pas d’icones…

    Je cherche donc.

    Voila, si ça peut aider des gens qui galèrent comme moi, ben c’est bien.

  17. aldahi
    25 avr 2011

    ok ok ok, je fatigue peut être un peu, c’est normal qu’ils soient vides, on nous dit comment les remplir dans la suite du tuto. Pardon.

    Je profite de ce post d’excuses pour poser une question, nul part dans le tuto on nous demande de faire les property et synthesize, alors que dans d’autres, c’est demandé. Est-ce propre à XCode 4 ? Pas utile ?

    Je les ai mis pour tabBarController :
    dans le h : @property (nonatomic, retain) UITabBarController *tabBarController;
    dans le m : @synthesize tabBarController;

    et ceci ne change rien à l’exécution du prog…

    Une explication ?

    En tout cas, merci beaucoup, tout ceci fait apprendre vite et bien !

    A

  18. 25 avr 2011

    @aldahi : Pour ta question concernant l’utilité des propriétés.
    Dans ce tutoriel, il n’est pas vraiment utile de faire une propriété avec le tabBarController pour une raison simple : ici, on n’instancie UITabBarController qu’à un seul endroit. La propriété c’est quand même fait pour que d’autres objets puissent l’utiliser. Comme dans notre exemple il n’y a nul autre objet, il n’y a donc pas d’intérêt particulier à créer une propriété.
    Cela étant dit, faire une propriété te permettra d’aller plus loin avec ton appli si tu le souhaites.

  19. ettibo
    12 juil 2011

    Bonjour,
    ton tuto es très bien, mais je voudrais le pousser le plus loin.
    Est-il possible de auto-hider le UITabBarController?
    J’ai essayé avec hidesBottomBarWhenPushed = YES mais rien ne se passe. Des idées?

  20. Staroun
    20 juin 2012

    Super. Merci bcp.

    ça aide énormément :)

    Continuez ainsi.

Une question, une suggestion, une opinion? Partagez ce que vous pensez, laissez un commentaire.

(obligatoire)
(obligatoire)

Note: Votre adresse email ne sera jamais publiée.

Suivez les réponses aux commentaires