RubyMotion - les cellules personnalisées

Synbioz

Dans cet article à propos de RubyMotion, nous allons voir comment mettre en place des cellules personnalisées qui seront utilisées dans un UITableView. Nous utiliserons comme base l'application de todo-list développée à l'occasion de l'article concernant RubyMotion et les tableviews.

Si vous prenez cette suite d'article en cours de route, RubyMotion est un framework permettant d'écrire des applications iOS et OS X natives en Ruby.

Vous pouvez récupérer le code de notre application sur GitHub et vous placer sur le commit « 7cf07001ae » qui correspond à l'état dans lequel nous avons laissé l'application à la fin de l'article précédent.

Cet article est publié avec l'aimable autorisation de Synbioz, l'article original peut être lu sur le blog de Synbioz : RubyMotion - les cellules personnalisées.

Commentez

- Titre : RubyMotion - les cellules personnalisées

- Auteur : Synbioz

- Parution : 7 janvier 2014

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Synbioz. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Création de cellule personnalisées

- II. Ajout des éléments

- II-A. Image de fond

- II-B. Nom de la tâche

- II-C. Ajout de la date

- II-D. Ajout du marqueur de priorité

- III. Conclusion

- IV. Remerciements

I - Création de cellule personnalisées

L'idée ici est de démontrer que nous ne sommes pas cantonnés aux types de cellules disponibles par défaut lorsqu'on construit une table. Il est possible d'être tout à fait original et d'aller beaucoup plus loin. Il s'avère d'ailleurs qu'en pratique, beaucoup d'applications utilisent leurs propres cellules personnalisées pour présenter leurs informations au sein d'une table.

Lorsque vous souhaitez sortir des sentiers battus, que votre designer vous propose une présentation des éléments élaborée, autre que celle livrée de base avec le SDK iOS, il vous faut créer des éléments personnalisés.

Ici nous souhaitons créer des cellules de tableau avec une présentation bien spécifique, pour ce faire, nous allons créer une classe héritant de UITableViewCell.

Dans le répertoire app/views, créons le fichier todo_table_view_cell.rb :

app/controllers/list_view_controller.rb

class TodoTableViewCell < UITableViewCell
TODO_CELL_REUSE_ID = "TodoTableViewCell"

attr_accessor :title, :date, :priority
end

Nous créons donc une classe héritant de UITableViewCell contenant trois attributs qui serviront pour stocker le titre de la tâche, sa date de création ainsi que sa priorité, ce qui permettra d'afficher un badge en fonction de celle-ci. Vous noterez qu'on définit également une constante qui sera utilisée comme identifiant de réutilisation des cellules comme nous l'avons déjà fait dans l'article précédent.

Jusque-là, nous avons créé nos cellules directement depuis ListViewController en passant par la méthode tableView:cellForRowAtIndexPath:, nous allons maintenant déplacer cette logique dans notre classe dédiée à la création de cellules. Voici donc la méthode à ajouter à TodoTableViewCell :

def self.cellForTask(task, inTableView:tableView)
cell = tableView.dequeueReusableCellWithIdentifier(TODO_CELL_REUSE_ID) || TodoTableViewCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier:TODO_CELL_REUSE_ID)
cell.title = task.name
cell.date = task.created_at
cell.priority = task.priority
cell.selectionStyle = UITableViewCellSelectionStyleNone
cell
end

Cette méthode permet de vérifier si la cellule correspondante est cachée. Si elle ne l'est pas, nous la créons.

Nous stockons ensuite le titre, la date de création et la priorité grâce à l'objet task qui a été passé. Nous définissons un style vide pour la cellule puisque nous voulons gérer nous même son aspect visuel. Finalement nous retournons cette cellule.

Il ne nous reste plus qu'à utiliser ces cellules personnalisées dans notre contrôleur ListViewController :

def tableView(tableView, cellForRowAtIndexPath:indexPath)
task = @tasks[indexPath.row]
TodoTableViewCell.cellForTask(task, inTableView:tableView)
end

Vous pouvez lancer l'application. Voici ce que vous obtenez :

La table est vide, aucune des cellules n'est remplie. En effet, lorsque vous utilisez des cellules personnalisées, il faut leur préciser comment afficher les informations. Nous allons donc, comme pour n'importe quel UIView, placer nos différent éléments en utilisant la méthode addSubview.

II - Ajout des éléments

II-A - Image de fond

Les UIView mettent à disposition la méthode layoutSubviews qui permet de définir comment seront disposées les vues enfants, nous allons l'utiliser pour disposer nos informations. Commençons par ajouter une image de fond à nos cellules :

def layoutSubviews
@background_image = UIImageView.alloc.initWithImage(UIImage.imageNamed("bgCell"))
self.addSubview(@background_image)
end

et dans app/controllers/list_view_controller.rb :

def tableView(tableView, heightForRowAtIndexPath:indexPath)
50
end

Nous ajoutons donc notre image de fond mais comme vous pouvez le remarquer, nous prenons le soin de préciser au contrôleur la hauteur de nos cellules pour qu'elle corresponde à la hauteur de notre image (50px ici). Par défaut, la hauteur appliquée aux cellules est de 44px ce qui masquerait une partie de notre image de fond.

Voici ce que vous obtenez en lançant l'application :

II-B - Nom de la tâche

Nous pouvons maintenant passer à l'ajout du nom de la tâche dans la cellule. Pour ce faire, nous allons enrichir la méthode layoutSubviews et ajouter une méthode dédiée à la création du label :

def layoutSubviews
@background_image = UIImageView.alloc.initWithImage(UIImage.imageNamed("bgCell"))
self.addSubview(@background_image)

self.addSubview(titleLabel)
end

def titleLabel
titleLabel = UILabel.alloc.initWithFrame([[10, 0], [300, 40]])
titleLabel.font = UIFont.fontWithName("AmericanTypewriter-Bold", size: 18)
titleLabel.textColor = UIColor.blueColor
titleLabel.adjustsFontSizeToFitWidth = true
titleLabel.backgroundColor = UIColor.clearColor
titleLabel.text = @title
titleLabel
end

Voici le résultat :

II-C - Ajout de la date

Aucune surprise ici puisque le principe va être exactement le même que pour l'ajout du nom de la tâche :

def layoutSubviews
@background_image = UIImageView.alloc.initWithImage(UIImage.imageNamed("bgCell"))
self.addSubview(@background_image)

self.addSubview(titleLabel)
self.addSubview(dateLabel)
end

def dateLabel
dateLabel = UILabel.alloc.initWithFrame([[10, 10], [300, 40]])
dateLabel.font = UIFont.fontWithName("AmericanTypewriter-Bold", size: 14)
dateLabel.textColor = UIColor.blackColor
dateLabel.adjustsFontSizeToFitWidth = true
dateLabel.backgroundColor = UIColor.clearColor
dateLabel.text = @date.strftime("%d/%M/%Y")
dateLabel
end

II-D - Ajout du marqueur de priorité

Nous allons maintenant ajouter à droite dans notre cellule un marqueur de priorité qui sera représenté par une image que nous ajoutons donc à notre dossier resources. Ce marqueur ne sera à afficher que si la tâche est en priorité haute :

def layoutSubviews
@background_image = UIImageView.alloc.initWithImage(UIImage.imageNamed("bgCell"))
self.addSubview(@background_image)

self.addSubview(titleLabel)
self.addSubview(dateLabel)
self.addSubview(priorityImage) if @priority == "Haut"
end

def priorityImage
priorityImage = UIImageView.alloc.initWithImage(UIImage.imageNamed("important"))
priorityImage.frame = ([[290, 8], [29, 29]])
priorityImage
end

La méthode d'ajout de l'image n'est appelée que si notre tâche en cours de rendu à une priorité haute, information que nous stockons dans une variable d'instance à la création d'une nouvelle cellule personnalisée.

Voyons un exemple de rendu avec deux tâches en priorité basse et une en priorité haute :

III - Conclusion

Nous avons vu dans cet article comment mettre en place un UITableViewCell pour pouvoir dépasser les limites des types de cellule disponibles par défaut. Vous pouvez donc exploiter cette possibilité pour intégrer un design personnalisé et mettre en œuvre toutes vos idées.

Un exercice intéressant pourrait être d'ajouter un bouton dans la cellule qui permettrait de modifier le statut (fait / à faire) de la tâche. Le bouton serait représenté par deux images qui alterneraient en fonction du statut.

Vous trouverez l'ensemble du code d'exemple de cet article, découpé en commits, sur GitHub.

IV - Remerciements

Cet article est publié avec l'aimable autorisation de Synbioz, l'article original peut être lu sur le blog de Synbioz : RubyMotion - les cellules personnalisées.