AIR Mobile – Les itemRenderer de List (LabelItemRenderer, IconItemRenderer, …)
Dans un des billets précédents, on a vu quels étaient les nouveaux composants Flex 4.5:
AIR Mobile – Les composants et le thème Mobile Flex 4.5
Mais il y a aussi d'autres composants qui sont un peu à part qui sont les itemRenderer. Comme vous le savez peut-être déjà, ce que l'on appelle un "itemRenderer" dans le langage Flex est un composant qui va être utilisé au sein d'une liste. Pour une liste, on a des lignes de données. Pour chaque ligne de données, on va devoir effectuer le rendu d'un point de vue graphique de cette ligne. Le rendu le plus basique est celui d'afficher un texte, tout simple.
Mais vous voudrez parfois représenter des données plus complexes, avec plusieurs champs ou des composants graphiques différents comme des images par exemple. Vous allez alors créer votre propre composant qui va afficher les données de votre liste comme vous le souhaitez, c'est ce que l'on appelle un "itemRenderer".
Utiliser les itemRenderer de Flex 4.5?
Il est donc possible de créer vos propres itemRenderer ou d'utiliser ceux prévus dans le SDK. Alors pourquoi utiliser ceux du SDK?
Et bien les itemRenderer du SDK comme LabelItemRenderer et IconItemRenderer sont optimisés à l’extrême pour un affichage le plus rapide possible. Les performances que vous aurez avec un IconItemRenderer seront toujours meilleurs que si vous crééz le votre avec 2 labels et une image. Les optimisations sont faîtes notamment sur les points suivants:
- Cache sur les images + délai d'affichage lors du scrolling
- Gestion des DPI pour les espacements
- Rendu des textes optimisé par l'utilisation du composant StyleableTextField
- Gestion des invalidations
C'est donc toute cette logique que vous n'aurez pas à coder. Mais si votre itemRenderer ne correspond pas à un itemRenderer pré-mâché du SDK, vous avez toujours la possibilité de créer le votre. S'il n'y a que des modifications mineures, je vous conseille cependant d'utiliser l'héritage pour ajouter vos modifications. Si vous partez vraiment from scratch, n'hésitez pas à vous inspirer du code des classes de Flex qui contiennent les meilleurs techniques d'optimisation.
Utilisation du LabelItemRenderer
Voici l'itemRenderer le plus simple, il va vous permettre d'afficher un Label.
Un petit exemple d'utilisation:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<fx:Declarations>
<s:ArrayCollection id="ac">
<fx:Array>
<fx:String>Ligne 1</fx:String>
<fx:String>Ligne 2</fx:String>
<fx:String>Ligne 3</fx:String>
<fx:String>Ligne 4</fx:String>
<fx:String>Ligne 5</fx:String>
<fx:String>Ligne 6</fx:String>
<fx:String>Ligne 7</fx:String>
<fx:String>Ligne 8</fx:String>
</fx:Array>
</s:ArrayCollection>
</fx:Declarations>
<s:List width="100%" height="100%" dataProvider="{ac}">
<s:itemRenderer>
<fx:Component>
<s:LabelItemRenderer />
</fx:Component>
</s:itemRenderer>
</s:List>
</s:View>
Et voilà le rendu dans le simulateur:

Pas impressionnant du tout mais les performances sont excellentes
.
Utilisation du composant IconItemRenderer
IconItemRenderer est un composant qui hérite de LabelItemRenderer, vous permettant d'aller bien plus loin dans l'affichage et dans la personnalisation.
Voici les éléments qu'il peut contenir:
- Un label "principal"
- Un label "secondaire" appelé "message" qui peut s'étendre sur plusieurs lignes
- Une image sur la gauche
- Une image sur la droite appelée "decorator", un chevron par exemple
Ce composant permet de réaliser la plupart des itemRenderers assez "classiques" que l'on peut retrouver sur les interfaces natives. Bien sûr, vous pouvez modifier les styles de chaque élément pour obtenir le style que vous souhaitez.
Voici un petit exemple:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<fx:Declarations>
<s:ArrayCollection id="ac">
<fx:Array>
<fx:Object mainLabel="Label ligne 1" messageLabel="message ligne 1" />
<fx:Object mainLabel="Label ligne 2" messageLabel="message ligne 2" />
<fx:Object mainLabel="Label ligne 3" messageLabel="message ligne 3" />
<fx:Object mainLabel="Label ligne 4" messageLabel="message ligne 4" />
<fx:Object mainLabel="Label ligne 5" messageLabel="message ligne 5" />
<fx:Object mainLabel="Label ligne 6" messageLabel="message ligne 6" />
<fx:Object mainLabel="Label ligne 7" messageLabel="message ligne 7" />
<fx:Object mainLabel="Label ligne 8" messageLabel="message ligne 8" />
</fx:Array>
</s:ArrayCollection>
</fx:Declarations>
<s:List width="100%" height="100%" dataProvider="{ac}">
<s:itemRenderer>
<fx:Component>
<s:IconItemRenderer messageField="messageLabel" labelField="mainLabel" iconFunction="myIconFunction"
decorator="@Embed('chev.jpg')">
<fx:Script>
<![CDATA[
[Embed(source='googleearth-icon.png')]
private const ICON:Class;
private function myIconFunction(item:Object):Class{
return ICON;
}
]]>
</fx:Script>
</s:IconItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
</s:View>
Et voilà le rendu de cet IconItemRenderer:

Bien sûr, vous pouvez personnaliser l'icône et le decorator de chaque ligne.
Voilà un petit exemple réalisé simplement en modifiant quelques propriétés CSS sur de la donnée dynamique:
Articles similaires
- AIR Mobile – Application Pokémon (7) – Modifier le style de la liste
- AIR Mobile – Les paramètres data et context de pushView
- AIR Mobile – Application TweetDeck (9) – Finalisation des styles de l'itemRenderer
- AIR Mobile – Les différents types de templates Flex Mobile
- AIR Mobile – Application TweetDeck (11) – Affichage d'un texte en fond lors du chargement des tweets
Aucun trackbacks pour l'instant







13 mai 2011
J'ai essayé de modifier quelques propriétés CSS :
@namespace s "library://ns.adobe.com/flex/spark";
s|View
{
backgroundColor: #494949;
chromeColor: #414141;
contentBackgroundColor: #414141;
alternatingItemColors: #414141;
}
global
{
color: white;
}
mais je n'arrive pas à modifier la couleur du séparateur d'items du composant List qui devient blanc, ce qui n'est pas très esthétique, je voudrais qu'il soit gris (#414141).
Si quelqu'un sait comment faire, merci.
13 mai 2011
Salut,
on dirait que cela n'est pas prévu pour pouvoir être modifié par du CSS. Si tu regardes le code de LabelItemRenderer (ligne 873), tu as:
// separators are a highlight on the top and shadow on the bottom
topSeparatorColor = 0xFFFFFF;
topSeparatorAlpha = .3;
bottomSeparatorColor = 0×000000;
bottomSeparatorAlpha = .3;
Donc tu auras toujours une ligne noire et une ligne blanche. Ou alors, il faut qu'au lieu d'utiliser LabelItemRenderer, tu crée une classe qui hérite de LabelItemRenderer et qui redéfinit la méthode drawBackground.
Fabien
13 mai 2011
comment procéder pour créer une classe qui hérite de LabelItemRenderer et qui redéfinit la méthode drawBackground, merci.
13 mai 2011
Dans le projet, click droit, New> ActionScript Class> Lui donner un nom. Ensuite, dans le corps de la classe:
override protected function drawBackground(unscaledWidth:Number,
unscaledHeight:Number):void {
// … code
}
Mais avant de faire cela, je vous conseille quand même de monter en compétence en ActionScript (voir tutoriaux sur http://www.flex-tutorial.fr/tutorial-flex-liste/) pour apprendre les bases de la programmation orientée objet
Fabien
14 mai 2011
Cela devrait fonctionner, ne pas oublier d'utiliser cette classe et pas l'itemRenderer de base.
Fabien
14 mai 2011
la couleur ne change pas, la classe et le mxml
14 mai 2011
@namespace s "library://ns.adobe.com/flex/spark";
s|View
{
backgroundColor: #494949;
chromeColor: #414141;
contentBackgroundColor: #414141;
alternatingItemColors: #414141;
}
global
{
color: white;
}
15 mai 2011
si je mets dans la balise List itemRenderer="DrawBackgroundIR" et que j'ai comme dans le tuto s:IconItemRenderer
le compilateur me renvoie plusieurs initialisateurs pour la propriété 'itemRenderer'
15 mai 2011
Il faut supprimer la balise iconitemrenderer si vous utilisez le votre
15 mai 2011
Avec iconItemRenderer il n'y a pas moyen de modifier la couleur du séparateur d'item ?
15 mai 2011
finalement ça fonctionne avec IconItemRenderer, j'ai créé un composant avec ma classe DrawBackgroundIR
<s:View xmlns:components="components.*"
15 mai 2011
Il y a quelque chose que je comprends pas
quand je mets import spark.components.LabelItemRenderer dans ma classe DrawBackgroundIR
je suis quand même obligé d'importer les classes déjà présentes dans spark.components.LabelItemRenderer
import flash.display.GradientType;
import flash.events.Event;
import flash.geom.Matrix;
import flash.text.TextLineMetrics;
import mx.controls.listClasses.*;
import mx.core.DPIClassification;
import mx.core.FlexGlobals;
import mx.core.IDataRenderer;
import mx.core.IFlexDisplayObject;
import mx.core.ILayoutElement;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import spark.components.supportClasses.InteractionState;
import spark.components.supportClasses.InteractionStateDetector;
import spark.components.supportClasses.StyleableTextField;
sinon j'ai une erreur du compilateur
18 mai 2011
Salut,
Cool que cela fonctionne au final. Tu n'es sûrement pas obligé d'importer toutes les classes définies dans IconItemRenderer, juste celle que tu utilises dans DrawBackgroundIR. Pour faire un clean, click droit > Source > Organize Imports.
Fabien
23 septembre 2011
Bonjour,
"Voilà un petit exemple réalisé simplement en modifiant quelques propriétés CSS sur de la donnée dynamique"
Possible d'avoir le code de l'exemple ? Merci !
23 septembre 2011
Salut,
Désolé, ce n'est pas possible (bout de code propriétaire) mais ce n'est pas très dûr à effectuer. Juste une couleur de fond en utilisant la propriété CSS "alternatingItemColors", un IconItemRenderer avec un icone et un decorator
Fabien
23 septembre 2011
En fait c'était plutôt l'aspect dynamique qui m'intriguais.
Je définis une icone dans mon objet item
[as][/as]
et j'imagine que myIconFunction doit donc renvoyer qqch comme item.icon mais il va renvoyer la chaîne et non l'asset embed ...
?
23 septembre 2011
Salut,
C'est un peu plus compliqué en fait, les images sont des PNG qui proviennent d'un serveur (dynamique, donc pas embeddable) et en plus, j'ai bidouillé le renderer pour qu'il puisse allez stocker et chercher les images dans une base SQLite en mode déconnecté
Fabien
23 septembre 2011
Ok pour tout ça mais si je voulais simplement afficher mon icone à partir de mon répertoire assets local ?
La question est en fait comment formater l'objet de retour de myIconFunction pour qu'il affiche la bonne icône à chaque ligne ?
Et merci pour ta réactivité
23 septembre 2011
Ok, alors soit tu déclares tes Embed et tu renvoies la variable Class depuis l'iconFunction, soit tu fais pour que l'iconFunction renvoie l'url de ton icône (même locale)
23 septembre 2011
Oui c'était ça l'idée : ne pas avoir à déclarer l'embed + 1 var pour chaque item.
Mais mon problème est que je récupère bien l'url locale ex. ./assets/picto/mon_picto.png mais c'est juste la chaîne qui va être retournée à mon iconFunction. J'imagine qu'avec le @Embed il doit y avoir un mécanisme un peu plus complexe qui va réellement récupérer l'icône
23 septembre 2011
Oui, quand c'est Embed, tu renvoies la variable de type Class qui a été "remplie" au moment de la compilation avec l'icône.
23 septembre 2011
Pour mon cas, en renvoyant directement la chaîne de type string à mon iconFunction ça passe bien.
Merci pour tes explications.
24 septembre 2011
Avec flex 4.5.1, le défilement du composant List est beaucoup moins fluide sur mon Galaxy S qu'avec flex 4.5
Adobe a alourdi le composant ?
24 septembre 2011
Salut,
non, il n'a pas été alourdi, vérifie que tu testes bien en release
Fabien
24 septembre 2011
je suis bien en release, ils ont corrigé des bugs, c'est peut-être pour ça que ça ralenti.
si la liste est longue, le défilement saccade.
24 septembre 2011
Pareil pour moi sur un HTC Desire. J'irai pas jusqu'à dire que le défilement saccade mais il est sans aucun doute moins fluide qu'une liste native Android. Et pas besoin d'avoir une longue liste : il suffit qu'elle dépasse de quelques items la hauteur de l'écran.
24 septembre 2011
la 4.5 est bien plus fluide
pour info http://www.adobe.com/devnet/flex/articles/whats-new-flex-flash-builder-46.html
26 septembre 2011
J'ai trouvé le soucis, c'était de ma faute.
27 septembre 2011
C'est toujours moins fluide quand même.
5 décembre 2011
dans flex 4.6, je ne trouve plus topSeparatorColor dans drawBackground
on dirait que cela n'est pas prévu pour pouvoir être modifié par du CSS. Si tu regardes le code de LabelItemRenderer (ligne 873), tu as:
// separators are a highlight on the top and shadow on the bottom
topSeparatorColor = 0xFFFFFF;
topSeparatorAlpha = .3;
bottomSeparatorColor = 0×000000;
bottomSeparatorAlpha = .3;
Donc tu auras toujours une ligne noire et une ligne blanche. Ou alors, il faut qu'au lieu d'utiliser LabelItemRenderer, tu crée une classe qui hérite de LabelItemRenderer et qui redéfinit la méthode drawBackground.
5 décembre 2011
c'est dans la fonction drawBorder
7 décembre 2011
J'utilise dans mon application un stageWebView et j'ai l'impression que c'est lui qui ralentit le défilement de mon composant List sur Android depuis Flex 4.5.1
9 décembre 2011
En passant la frameRate à 48 c'est plus fluide sur SGS.
29 mars 2012
svp est ce qu'il serait possible de mettre le labelfield en dessous de l'iconfield ?
merci bien
29 mars 2012
Salut,
Il faut faire ton propre itemRenderer si tu veux avoir un texte de taille variable (multi-ligne) puis un texte simple en dessous. Pour éviter de répéter le code, tu fais un simple héritage sur l'itemRenderer de base puis tu redéfinis des méthodes comme layoutContents.
Petite explication dans cet article où je fais exactement cela:
http://www.flex-tutorial.fr/2011/08/27/air-mobile-application-tweetdeck-8-creation-dun-itemrenderer-pour-lobjet-tweet/
Fab
29 mars 2012
merci, mais j'ai un autre petit problème. je ne sais pas où je vais mettre ce code
et vu que moi je veux mettre mon labelfield juste en dessous de la photo, je ne sais pas à quoi cet extrait de code va me servir et je ne le comprends pas très bien
var hasLabel:Boolean = labelDisplay && labelDisplay.text != "";
var hasMessage:Boolean = messageDisplay && messageDisplay.text != "";
if (hasLabel && hasMessage){
var labelY:Number = labelDisplay.y;
var messageY:Number = messageDisplay.y;
messageDisplay.y = labelY;
labelDisplay.y = labelY + messageDisplay.height;
ps: je suis nouveau sous flex
29 mars 2012
Salut,
si tu veux mieux comprendre, télécharge les sources du projet:
http://www.flex-tutorial.fr/wp-content/uploads/tweetdeck/TweetDeck-3.fxp
Fabien
30 mars 2012
merci fabien !!!!!!!!!!!
4 avril 2012
comment modifier l'entête d'un panel sous flex et y ajouter à cette entête un bouton du style"+"?
tout en sachant que je suis sous version mobile!!!!!!!!!!!
merci d'avance
4 avril 2012
Salut,
Essaie en modifiant la skin, c'est expliqué ici:
http://stackoverflow.com/questions/3932926/adding-an-image-on-the-right-side-of-the-title-bar-of-a-panel-in-flex-4
Fabien
4 avril 2012
svp
4 avril 2012
erreur de frappe ....... merci fabien
4 avril 2012
Et stp excuses moi, jai plutot voulu dire augmenter la taille de l'entête du panel sous version mobile!!!
4 avril 2012
http://blog.flexexamples.com/2010/07/25/setting-the-header-height-on-a-spark-panel-container-in-flex-4/
4 avril 2012
@fab: La prochaine fois, utilise http://bit.ly/HezImC
10 avril 2012
bonjour à tous,
en ce moment je travaille sur le développement d'une application qui va être sur les tablettes. Et je la développe sous "flex"; svp j'aimerai savoir comment générer un appui long (long press) avec flex pour certaines fonctionnalités de mon application.
11 avril 2012
Salut andy,
Ca n'existe pas de base mais il est facile de le faire en quelques lignes de code. Ce projet devrait te donner les billes nécessaires:
https://github.com/fljot/Gestouch
Fabien