SDK iOS Création de cellules UITableView personnalisées

Une poignée de styles de cellules prédéfinis sont disponibles pour les développeurs depuis iOS 3. Ils sont pratiques et très utiles pour le prototypage, mais dans de nombreux cas, vous avez réellement besoin d'une solution personnalisée adaptée aux besoins du projet sur lequel vous travaillez. Dans ce didacticiel, je vais vous montrer comment personnaliser des cellules d’affichage de tableau à l’aide de cellules statiques et prototypes, ainsi que de sous-classes. UITableViewCell.


Anatomie d'une cellule de vue de tableau

Même si UITableViewCell hérite directement de UIView, son anatomie est plus complexe que prévu. Si vous envisagez de sous-classer UITableViewCell, il est nécessaire de comprendre l'anatomie d'une cellule vue de table. À la base, une cellule de vue de tableau n’est rien de plus qu’une vue avec plusieurs sous-vues, une vue d’arrière-plan et sélectionnée, une vue de contenu et plusieurs autres sous-vues plus exotiques, telles que la vue accessoire à droite. Regardons les différentes sous-vues.

Affichage du contenu

Comme son nom l'indique, la vue du contenu contient le contenu de la cellule. Selon le style de la cellule, cela peut inclure une ou deux étiquettes et une vue d'image. Comme le souligne la documentation, il est important d'ajouter des sous-vues personnalisées à la vue de contenu de la cellule, car cela garantit que les sous-vues de la cellule sont correctement positionnées, redimensionnées et animées lorsque les propriétés de la cellule changent. En d'autres termes, une cellule de vue de tableau s'attend à ce que son contenu se trouve dans sa vue de contenu. Il en va de même pour une cellule de vue de collection, qui est pratiquement identique à une cellule de vue de tableau en termes de hiérarchie de vues..

Vue accessoire

La vue accessoire d'une cellule de vue de table peut être n'importe quel type de vue. Vous connaissez probablement déjà les vues des indicateurs de divulgation et de divulgation détaillée. Cependant, une vue accessoire peut également être un bouton, un curseur ou une commande pas à pas. Regardez le Réglages application sur un appareil iOS pour avoir une idée de certaines des possibilités. N'oubliez pas que l'espace d'une vue accessoire est limité pour une cellule de vue de tableau standard. Cela signifie que toutes les vues ne peuvent ou ne doivent pas être utilisées comme vue accessoire..

Contrôle de modification et de réorganisation

Le contrôle d'édition est une autre sous-vue d'une cellule de la vue tableau qui se glisse dans et en dehors de la vue lorsque le mode d'édition de la vue tableau change. Lorsqu'une vue de tableau passe en mode d'édition, il est demandé à la source de données de la vue de tableau quelles cellules de vue de tableau sont modifiables en lui envoyant un message de tableView: canEditRowAtIndexPath: pour chaque cellule actuellement visible. Les cellules de vue de tableau modifiables sont invitées à passer en mode d'édition, ce qui affiche le contrôle d'édition à gauche et, le cas échéant, le contrôle de réorganisation à droite. Une cellule de vue de tableau en mode édition masque sa vue accessoire pour laisser de la place au contrôle de réorganisation et au bouton de confirmation de suppression qui apparaît à droite lorsqu'une ligne est marquée pour suppression..

Vues de fond

Les vues d'arrière-plan et d'arrière-plan sélectionnées sont positionnées derrière toutes les autres sous-vues d'une cellule de vue de tableau. Outre ces vues d’arrière-plan, le UITableViewCell La classe définit également une vue d’arrière-plan (multipleSelectionBackgroundView) utilisé pour les vues de tableau prenant en charge la sélection multiple.


Styles Prédéfinis

Dans ce tutoriel, je ne parlerai pas beaucoup des styles de cellules de vue de tableau prédéfinis. L'objectif principal de ce didacticiel est de vous montrer comment personnaliser les cellules d'une vue de tableau d'une manière impossible avec les styles de cellules de vue de tableau prédéfinis. Gardez toutefois à l'esprit que ces styles de cellules prédéfinis sont assez puissants pour personnaliser une cellule d'affichage de tableau. le UITableViewCell classe expose primaire (textLabel) et secondaire (detailTextLabel) étiquette ainsi que la vue de l'image de la cellule (imageView) sur la gauche. Ces propriétés offrent un accès direct aux sous-vues de la cellule, ce qui signifie que vous pouvez modifier directement les attributs d'une étiquette, tels que sa police et la couleur du texte. La même chose est vraie pour l'affichage de l'image de la cellule.

Malgré la flexibilité offerte par les styles de cellules prédéfinis, il n'est pas recommandé de repositionner les différentes sous-vues. Si vous souhaitez plus de contrôle en termes de disposition des cellules, vous devez choisir un autre itinéraire..


Option 1: cellules statiques

Une vue tableau peuplée de cellules statiques est de loin la mise en œuvre la plus simple d'une vue tableau du point de vue d'un développeur. Comme son nom l'indique, une vue tabulaire avec des cellules statiques est statique, ce qui signifie que le nombre de lignes et de sections est défini à la compilation, pas à l'exécution. Toutefois, cela ne signifie pas que le contenu de la cellule ne peut pas être modifié au moment de l'exécution. Laissez-moi vous montrer comment tout cela fonctionne.

Créez un nouveau projet dans Xcode en sélectionnant le Application à vue unique modèle, nommez-le Statique (figure 1), et activez les storyboards et le comptage automatique des références (ARC). Au moment de la rédaction de cet article, les cellules statiques ne sont disponibles qu'en combinaison avec des storyboards.


Les cellules statiques ne peuvent être utilisées qu’avec un UITableViewController, ce qui signifie que nous devons changer la super-classe du contrôleur de vue existant pour UITableViewController. Avant de jeter un coup d’œil sur le scénarimage, ajoutez trois sorties comme indiqué ci-dessous. Cela nous permettra de modifier le contenu des cellules statiques que nous allons créer dans le storyboard..

#importation  @interface MTViewController: UITableViewController @property (faible, non atomique) IBOutlet UILabel * firstLabel; @property (faible, non atomique) IBOutlet UILabel * secondLabel; @property (faible, nonatomique) IBOutlet UILabel * thirdLabel; @fin

Ouvrez le scénariseur principal, sélectionnez le contrôleur de vue et supprimez-le. Faites glisser un contrôleur de vue de la table Bibliothèque d'objets et changer sa classe à MTViewController dans le Inspecteur d'identité (Figure 2). Sélectionnez la vue table du contrôleur de vue et définissez son Contenu attribuer à Cellules statiques dans le Inspecteur d'attributs (figure 3). Sans avoir à mettre en œuvre le UITableViewDataSource protocole, la vue de la table sera aménagée comme défini dans le storyboard.



Vous pouvez le tester en ajoutant plusieurs étiquettes aux cellules statiques et en connectant les trois prises définies dans MTViewController.h il y a quelques instants (figure 4). Comme je l'ai mentionné précédemment, le contenu des étiquettes peut être défini lors de l'exécution. Regardez l'implémentation de la vue du contrôleur viewDidLoad au dessous de.


- (void) viewDidLoad [super viewDidLoad]; // Configurer les étiquettes [self.firstLabel setText: @ "First Label"]; [self.secondLabel setText: @ "Deuxième étiquette"]; [self.thirdLabel setText: @ "Troisième étiquette"]; 

Générez et exécutez l'application dans le simulateur iOS pour voir le résultat. Les cellules statiques sont assez puissantes, en particulier pour les applications de prototypage. Ils sont très utiles lorsque la présentation d'une vue sous forme de tableau ne change pas, par exemple dans les paramètres d'une application ou à propos d'une vue. En plus de spécifier le nombre de lignes et de sections d'une vue sous forme de tableau, vous pouvez également insérer des en-têtes et des pieds de section personnalisés..


Option 2: Cellules prototypes

Un autre grand avantage de l'utilisation des storyboards est la cellule prototype, qui a été introduite conjointement avec les storyboards dans iOS 5. Les cellules de prototype sont des modèles renseignés de manière dynamique. Chaque cellule prototype est identifiée par un identifiant de réutilisation grâce auquel la cellule prototype peut être référencée dans le code. Regardons un autre exemple.

Créez un nouveau projet Xcode basé sur le Application à vue unique modèle. Nommez le projet Prototype et activez les storyboards et ARC pour le projet (figure 5). Comme nous l'avons fait dans l'exemple précédent, changez la sous-classe du contrôleur de vue (MTViewController) à UITableViewController. Il n'est pas nécessaire de déclarer les points de vente dans cet exemple.


#importation  @interface MTViewController: UITableViewController @end

Comme nous l'avons fait dans l'exemple précédent, supprimez le contrôleur de vue existant dans le scénarimage principal et faites glisser un contrôleur de vue de tableau à partir du Bibliothèque d'objets. Changez la classe du nouveau contrôleur de vue de table en MTViewController dans le Inspecteur d'identité.

Comme je l'ai mentionné précédemment, chaque cellule prototype possède un identifiant de réutilisation permettant de la référencer. Sélectionnez la cellule prototype dans la vue tableau et définissez sa Identifiant à CellIdentifier comme indiqué dans la figure ci-dessous (figure 6).


Comme pour les cellules statiques, vous pouvez ajouter des sous-vues à la vue de contenu de la cellule prototype. Il n'est pas nécessaire de spécifier le nombre de lignes et de sections comme nous l'avions fait dans le projet précédent. Lors de l’utilisation de cellules prototypes, il est nécessaire d’implémenter le protocole de source de données de vue tableau (UITableViewDataSource). Vous vous demandez peut-être comment nous référençons les sous-vues de la vue de contenu de la cellule prototype? Il y a deux options. L’option la plus simple est de donner à chaque vue une étiquette et demandez à la vue de contenu de la cellule la sous-vue avec une balise particulière. Voyons comment cela fonctionne.

Ajoutez une étiquette à la cellule prototype et définissez son étiquette sur 10 dans le champ Inspecteur d'attributs (figure 7). dans le MTViewController classe, nous implémentons le protocole de source de données table view comme indiqué ci-dessous. L'identifiant de réutilisation de cellule est déclaré en tant que constante de chaîne statique..


static NSString * CellIdentifier = @ "CellIdentifier";
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return 5;  - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section return 5;  - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier]; // Configuration de la cellule UILabel * label = (UILabel *) [cell.contentView viewWithTag: 10]; [label setText: [NSString stringWithFormat: @ "Ligne% i dans la section% i", [ligne indexPath], [section section indexPath]]]; cellule de retour;  - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath return NO;  - (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return NO; 

Exécutez l'application dans le simulateur iOS pour voir le résultat. Même s'il semble facile de travailler avec des cellules prototypes en utilisant des balises pour identifier les sous-vues, cela devient rapidement gênant lorsque la disposition de la cellule est plus complexe. Une meilleure approche consiste à utiliser un UITableViewCell sous-classe. Créez une nouvelle classe Objective-C, nommez-la MTTableViewCell, et en faire une sous-classe de UITableViewCell. Ouvrez le fichier d'en-tête de la nouvelle classe et créez un point de vente de type. UILabel nommé étiquette principale.

#importation  @interface MTTableViewCell: UITableViewCell @property (faible, non atomique) IBOutlet UILabel * mainLabel; @fin

Avant de pouvoir utiliser notre sous-classe, nous devons apporter quelques modifications au scénarimage principal. Ouvrez le scénario principal, sélectionnez la cellule prototype, puis définissez sa classe sur MTTableViewCell dans le Inspecteur d'identité (figure 8). Ouvrez le Inspecteur de connexions et connectez le étiquette principale sortie avec l'étiquette que nous avons ajoutée à la cellule prototype (figure 9).



Les modifications apportées au storyboard nous permettent de refactoriser la tableView: cellForRowAtIndexPath: comme indiqué ci-dessous. N'oubliez pas d'importer le fichier d'en-tête du MTTableViewCell classe. J'espère que vous acceptez que cette modification rend notre code plus lisible et maintenable.

#import "MTTableViewCell.h"
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath MTTableViewCell * cell = (MTTableViewCell *) [tableView dequeueReusableCellWithIdentifier: CellIdentifier]; // Configurer la cellule [cell.mainLabel setText: [NSString stringWithFormat: @ "Ligne% i dans la section% i", [ligne indexPath], [section section indexPath]]]; cellule de retour; 

Exécutez l'application dans le simulateur iOS. Les cellules prototypes sont un composant merveilleux des storyboards. Ils facilitent la personnalisation des cellules de la vue tableau avec un minimum d'effort.


Option 3: sous-classement

Dans l'exemple précédent, nous avons créé un programme personnalisé. UITableViewCell sous-classe. Cependant, nous n'avons pas vraiment exploité le pouvoir du sous-classement. Au lieu de cela, nous nous sommes appuyés sur la polyvalence des cellules prototypes. Dans la troisième et dernière option, je vous montre comment créer un UITableViewCell sous-classe sans utiliser de cellules prototypes. Il existe plusieurs stratégies pour créer un UITableViewCell sous-classe et celle que je vais vous montrer dans l'exemple suivant n'est en aucun cas le seul moyen. Avec cet exemple, je veux illustrer en quoi la sous-classification diffère des deux premières options dans lesquelles nous utilisions Interface Builder et les storyboards..

Créez un nouveau projet Xcode basé sur le Application à vue unique modèle, nommez-le Sous-classe, et activez ARC pour le nouveau projet. Assurez-vous que la case à cocher intitulée Utiliser des storyboards n'est pas cochée (figure 10).


Comme nous l'avons fait dans les deux exemples précédents, commençons par changer le contrôleur de vue (MTViewController) superclasse à UITableViewController. Ouvrez le fichier XIB du contrôleur de vue, supprimez la vue du contrôleur de vue et faites glisser une vue de tableau du Bibliothèque d'objets. Sélectionnez la vue tableau et définissez son la source de données et déléguer débouchés au Propriétaire du fichier, c'est-à-dire le contrôleur de vue. Sélectionnez le Propriétaire du fichier et mettre sa vue sortie vers la vue de table (figure 11).

#importation  @interface MTViewController: UITableViewController @end

Avant de créer une sous-classe personnalisée de UITableViewCell, Commençons par implémenter le protocole de source de données de la table pour s’assurer que tout fonctionne comme prévu. Comme nous l'avons fait précédemment, il est recommandé de déclarer l'identificateur de réutilisation de cellule en tant que constante de chaîne statique. Pour faciliter la réutilisation (et l’initialisation) des cellules, nous envoyons à la vue tableau un message de registerClass: forCellReuseIdentifier: et passez un nom de classe et l'identifiant de réutilisation de cellule comme premier et second paramètres. Cela donne à la vue tableau toutes les informations nécessaires pour instancier de nouvelles cellules lorsqu'aucune cellule réutilisable n'est disponible. Qu'est-ce que cela nous gagne? Cela signifie que nous n'avons jamais explicitement à instancier une cellule. La vue de table s’occupe de cela pour nous. Tout ce que nous avons à faire est de demander à la vue tableau de nous retirer une cellule. Si une cellule réutilisable est disponible, la vue tableau nous en renvoie une. Si aucune cellule n'est disponible pour une réutilisation, la vue tabulaire en crée automatiquement une en arrière-plan. Un bon endroit pour enregistrer une classe pour la réutilisation de cellules est dans le contrôleur de vue. viewDidLoad méthode (voir ci-dessous).

static NSString * CellIdentifier = @ "CellIdentifier";
- (void) viewDidLoad [super viewDidLoad]; // Classe de registre pour l'identificateur de réutilisation de cellule [self.tableView registerClass: [classe UITableViewCell] forCellReuseIdentifier: CellIdentifier]; 
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return 5;  - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section return 5;  - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier pourIndexPath: indexPath]; // Configurer la cellule [cell.textLabel setText: [NSString stringWithFormat: @ "Ligne% i dans la section% i", [ligne indexPath], [section section indexPath]]]; cellule de retour;  - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath return NO;  - (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath return NO; 

La sous-classe que nous sommes sur le point de créer est assez simple. Mon but est de vous montrer ce qui se passe sous le capot et ce qui est nécessaire pour créer un UITableViewCell sous-classe, par opposition à l’utilisation de cellules statiques ou prototypes. Créez une nouvelle classe Objective-C, nommez-la MTTableViewCell, et en faire une sous-classe de UITableViewCell. Ouvrez le fichier d'en-tête de la classe et ajoutez une propriété publique de type. UILabel avec un nom de étiquette principale.

#importation  @interface MTTableViewCell: UITableViewCell @property (fort, non atomique) UILabel * mainLabel; @fin

Comme vous pouvez le voir ci-dessous, la mise en œuvre de MTTableViewCell n'est pas compliqué. Nous ne faisons que remplacer la superclasse initWithStyle: reuseIdentifier: méthode. Cette méthode est invoquée par la vue table lorsqu'elle instancie une classe pour nous. L'inconvénient de donner à la vue tableau l'autorisation d'instancier des cellules est que vous ne pouvez pas spécifier le premier argument de cette méthode, le style de la cellule. Vous pouvez en savoir plus à ce sujet sur Stack Overflow.

Dans initWithStyle: reuseIdentifier:, nous initialisons l'étiquette principale, la configurons et l'ajoutons à la vue du contenu de la cellule. Comme je l'ai expliqué dans l'introduction, cette dernière est très importante si vous souhaitez que la cellule personnalisée se comporte comme une cellule d'affichage de tableau standard..

- (id) initWithStyle: (UITableViewCellStyle) style reuseIdentifier: (NSString *) reuseIdentifier self = [super initWithStyle: style reuseIdentifier: reuseIdentifier]; if (self) // Helpers CGSize size = self.contentView.frame.size; // Initialise l'étiquette principale self.mainLabel = [[UILabel alloc]] initWithFrame: CGRectMake (8.0, 8.0, size.width - 16.0, size.height - 16.0)]; // Configurer l'étiquette principale [self.mainLabel setFont: [UIFont boldSystemFontOfSize: 24.0]]; [self.mainLabel setTextAlignment: NSTextAlignmentCenter]; [self.mainLabel setTextColor: [UIColor orangeColor]]; [self.mainLabel setAutoresizingMask: (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; // Ajouter une étiquette principale à la vue du contenu [self.contentView addSubview: self.mainLabel];  retourner soi-même; 

Pour utiliser notre nouvelle classe, importez son fichier d’en-tête dans MTViewController.m, mettre à jour le contrôleur de vue viewDidLoad méthode et modifier les tableView: cellForRowAtIndexPath: méthode du protocole de source de données d'affichage de table, comme indiqué ci-dessous.

#import "MTTableViewCell.h"
- (void) viewDidLoad [super viewDidLoad]; // Classe de registre pour l'identificateur de réutilisation de cellule [self.tableView registerClass: [classe MTTableViewCell] forCellReuseIdentifier: CellIdentifier]; 
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath MTTableViewCell * cell = (MTTableViewCell *) [tableView dequeueReusableCellWithIdentifier: CellIdentifier pourIndexPath: // Configurer la cellule [cell.mainLabel setText: [NSString stringWithFormat: @ "Ligne% i dans la section% i", [ligne indexPath], [section section indexPath]]]; cellule de retour; 

Sous-classement UITableViewCell est un sujet beaucoup plus impliqué que ce que j'ai discuté dans ce tutoriel. Si vous voulez que je vous en dise plus sur ce sujet, faites-le moi savoir dans les commentaires ci-dessous. N'oubliez pas de lancer l'application dans le simulateur iOS pour voir la sous-classe en action.


Conclusion

Quels sont les avantages de l’utilisation d’une sous-classe personnalisée par rapport à l’utilisation de cellules prototypes? La réponse simple est la flexibilité et le contrôle. Malgré leur utilité, les cellules prototypes ont leurs limites. Le principal obstacle auquel de nombreux développeurs sont confrontés lors du sous-classement UITableViewCell c'est le fait que c'est fastidieux. Écrire du code d'interface utilisateur est fastidieux et peu de gens, s'il en est, l'apprécient. Apple a créé Interface Builder pour de bonnes raisons. Il est également possible de créer des cellules de vue de tableau personnalisées à l'aide d'Interface Builder et de charger le fichier XIB au moment de l'exécution. Je crée généralement des cellules de vue de tableau complexes dans Interface Builder et convertis la conception en code lorsque je suis satisfait du résultat. Cette astuce vous fait gagner beaucoup de temps.

Si vous devez utiliser Interface Builder pour créer des cellules de vue de tableau personnalisées ou créer des UITableViewCell les sous-classes à partir de zéro dépendent vraiment de la situation et de vos préférences. Cependant, il est clair qu'Interface Builder est devenu plus puissant et que l'introduction de Xcode 4 représentait un autre grand pas en avant, malgré les premiers bogues et problèmes dont elle souffrait..

Les cellules statiques semblent très agréables au premier abord, mais vous allez rapidement rencontrer des limitations. Cependant, vous ne pouvez pas nier que c'est un moyen très rapide de prototyper une application..

J'espère que vous avez apprécié ce tutoriel. Si vous travaillez avec iOS tout le temps, pourquoi ne pas consulter la gamme de plus de 1 000 modèles d'applications iOS sur Envato Market? Avec tout, des utilitaires iOS et des éléments d'interface utilisateur aux modèles d'applications audio et vidéo, vous êtes certain de trouver quelque chose qui peut accélérer votre flux de travail..

Modèles d'applications iOS sur Envato Market

Ou vous pouvez vous diriger vers Envato Studio, où vous trouverez des développeurs Android prêts à travailler sur tous les projets, grands ou petits..

Développeurs d'applications sur Envato Studio