Cet article est publié sous licence CC BY-NC-SA
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 donc comme base l’application de todo 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.
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
:
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 au sein de la cellule. Nous allons donc, comme pour n’importe quel UIView
, placer nos différent éléments en utilisant la méthode addSubview
.
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 :
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 :
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
Nous allons maintenant ajouter à droite dans notre cellule un marqueur de priorité qui sera représentée 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 à un 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 :
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 cet article, découpé en commits sur GitHub.
L’équipe Synbioz.
Libres d’être ensemble.
Nos conseils et ressources pour vos développements produit.