Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

28août/110

AIR Mobile – Application TweetDeck (9) – Finalisation des styles de l'itemRenderer

Dans le dernier tutorial, on a vu comment créer un itemRenderer pour les Tweet. Avec quelques hacks pour combler un bug de Flex mais cela fonctionnait quand même:

AIR Mobile – Application TweetDeck (8) – Création d'un itemRenderer pour l'objet Tweet

Avant de continuer, on va essayer de faire pour que notre itemRenderer ait la tête de celui de TweetDeck:

Tout d'abord, on va changer la couleur du fond. Pour cela, on va utiliser une propriété CSS d'IconItemRenderer:"alternatingItemColors". Dans notre cas, les couleurs sont toujours les mêmes, il nous suffit donc de donner une couleur.

Dans le code de l'application principale "TweetDeck.mxml", rajoutez un tag "Style":

<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                            xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.TweetDeckHomeView">
  <fx:Style>
    @namespace s "library://ns.adobe.com/flex/spark";
    s|IconItemRenderer{
      alternatingItemColors:#565556;
    }
  </fx:Style>
</s:ViewNavigatorApplication>

Le rendu:

Pour la couleur du texte de la deuxième ligne, on va utiliser le style CSS "color" qui s'applique au labelDisplay (dans notre cas, en bas):

    s|IconItemRenderer{
      alternatingItemColors:#565556;
      color:#B5B6B5;
    }

Maintenant, il nous faut afficher le texte en blanc et pas en noir. En temps normal, il suffirait de rajouter des styles sur IconItemRenderer mais avec notre hack pour l'affichage du texte HTML, on ne peut plus. On va donc indiquer cela dans le contenu HTML. Dans la méthode formatMessage de TweetRenderer.as, remplacez donc la dernière ligne par:

return "<font size=\"" + fontSize + "\" face=\"Arial\" color=\"#FFFFFF\">" + value.replace(urlPattern, "<a href='$1$2$3'>$1$2$3</a>") + "</font>";

Rendu:

Maintenant, les liens doivent aussi être en #B5B6B5. Cela se passe dans la construction de notre StyleSheet dans TweetRenderer.as:

var styles:String = "a {color: #B5B6B5;}";

Rendu:

Maintenant, un petit problème d'ordre esthétique, lorsque les images (icônes) sont en train de charger, elles ne prennent aucune place.

27août/113

AIR Mobile – Application TweetDeck (8) – Création d'un itemRenderer pour l'objet Tweet

Dans le tutorial précédent, on a vu comment interroger le service Twitter et comment afficher une liste de Tweet dans une liste:

AIR Mobile – Application TweetDeck (7) – Afficher une liste de Tweet

Le résultat est un peu décevant car de base, on ne peut afficher qu'une ligne de texte. Voilà par exemple le rendu d'un tweet sur TweetDeck:

En gros, on a :

  • Une photo toujours de la même taille, en haut à gauche
  • Un texte multi-ligne (le tweet) avec potentiellement des liens URL
  • Un texte sur une ligne (le nom de l'utilisateur)

Sur le screenshot, il y a aussi le nombre de likes et de commentaires, qui est propre à Facebook. On va se limiter à Twitter pour le moment :)

Classes d'itemRenderer disponibles avec Flex

A partir de là, la grosse erreur que l'on pourrait faire, c'est d'aller coder à la main son itemRenderer de 0. Alors qu'il y a peut-être des classes qui pourraient nous aider. J'avais écrit un article là-dessus sur flex-tutorial.fr:

AIR Mobile – Les itemRenderer de List (LabelItemRenderer, IconItemRenderer, …)

Le composant IconItemRenderer semble parfait pour la tâche puisqu'il a déjà deux labels et une image. Quelques points bloquants cependant:

  • Le texte multi-ligne vient en second
  • Le texte multi-ligne ne supporte pas les liens URL

On pourrait adapter simplement le design en mettant le texte multi-ligne en bas et ne pas s'en pré-occuper mais pendant qu'on est à faire un clone de TweetDeck, autant faire attention aux détails.

La prochaine partie du tutorial sera un peu "avancée", vous pouvez la sauter si cela vous semble trop complexe.

Création de l'itemRenderer

Pour notre itemRenderer, on va donc hériter de IconItemRenderer. Faites donc un clic droit sur le package "views" > New > ActionScript Class. Nommez cette classe "TweetRenderer", Based On IconItemRenderer puis finish. Pour pouvoir effectuer nos tests, on va directement l'assigner sur notre liste:

  <s:List width="100%" height="100%" dataProvider="{searchResult.lastResult.results}"
          labelField="from_user">
    <s:itemRenderer>
      <fx:Component>
        <views:TweetRenderer iconField="profile_image_url"
                             labelField="from_user"
                             messageField="text" />
      </fx:Component>
    </s:itemRenderer>
  </s:List>

Voici le rendu provisoire:

Première étape: inversion du label et du message

Pour commencer, on va inverser la position des deux textes. Il faut bien faire attention que le texte du message est multi-ligne, la hauteur de l'itemRenderer est donc conditionnée par ce composant. Tout se passe dans la méthode "layoutContents" qui fait le calcul des tailles et du placement des éléments. On va surcharger cette méthode et inverser la position des éléments.

Pour éviter de vous taper la signature de la méthode layoutContents, on va utiliser une fonctionnalité de Flash Builder. Sur l'éditeur de code de TweetRenderer, faites clic droit puis Source puis Override / Implements methods…:

Cochez la méthode layoutContents et validez. Moins de risques d'erreur de cette manière. Dans la classe de base, on va récupérer un bout de code qui nous sera utile:

var hasLabel:Boolean = labelDisplay && labelDisplay.text != "";
var hasMessage:Boolean = messageDisplay && messageDisplay.text != "";

Comme cela, on a la détection de la présence ou pas des composants. Dans notre cas, on cherche juste à faire le switch quand le renderer dessine les 2 composants:

package views{
  import spark.components.IconItemRenderer;

  public class TweetRenderer extends IconItemRenderer{
    public function TweetRenderer(){
      super();
    }

    override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void{
      super.layoutContents(unscaledWidth, unscaledHeight);

      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;
      }
    }

  }
}

Voici le rendu:

Bon, voilà, c'était assez simple pour cette partie. Maintenant, on va essayer d'afficher les liens URL différemment.

Deuxième étape : Afficher les liens URL

Autant la première étape était simple, autant la 2ème est plus corsée. Le service Twitter vous renvoie un contenu texte brut. Ce n'est pas du html, par exemple on a "Woo! I got 100% on the Adobe Illustrator quiz. Try it!  http://t.co/mrE3QOo via @envatovectors". La première mission va être de détecter ces liens dans le texte pour pouvoir les afficher différemment.

Pour ce genre de mission (recherche de chaîne dans une chaîne), et dans tous les langages, vous devriez avoir un premier réflexe : les expressions régulières. C'est l'arme parfaite pour s'attaquer à ce genre de problèmes. Mais si comme moi, vous n'êtes pas un "regexp-wizard", même détecter une URL dans un texte devient difficile.

 

Remplis sous: Adobe Air, Styles Lire la suite
23juin/111

AIR Mobile – Application Pokémon (16) – Réaliser une Skin de bouton générique

Les applications mobiles ne dérogent pas à la règle. Pour avoir une bonne application, il faut qu'elle soit fonctionnelle et agréable à l'oeil. Pour l'aspect fonctionnel, c'est souvent votre job en tant que développeur. Quant à l'aspect graphisme, c'est souvent réservé aux graphistes qui vous fournissent des maquettes. Mais on a pas toujours un graphiste sous la main, encore plus si vous faîtes une application perso avec des Pokémon dedans.

Heureusement, le look par défaut des composants Flex peut parfois être suffisant. Mais vous ne voulez pas que votre application ressemble à toutes les autres, il va donc falloir passer par l'étape du Skinning. Pas de panique, même si vous n'avez pas la fibre artistique, c'est très simple. Pour cela, pas besoin (on pourrait) de sortir des outils comme Photoshop ou Illustrator, on va tout faire dans le code.

Le résultat attendu

Si vous avez suivi tous les tutoriaux dans l'ordre, vous n'avez pas pu manquer le premier, celui sur l'étape de prototypage dans Balsamiq:

AIR Mobile – Application Pokémon (1) – Conception et maquettage

On avait définit le bouton comme ceci:

maq

Plutôt simple, un texte et un icône à droite. D'ailleurs, le bouton "Evolution de …" y ressemble étrangement, on va pouvoir mutualiser les développements.

Utilisation des propriétés de Button par défaut

Il existe déjà une propriété "icon" sur button. Essayons donc le code suivant:

...
<s:Button id="soundButton" label="Ecouter le cri de {_p.nom}" click="onSoundClick(event)"
	icon="@Embed(source='/assets/sound_high.png')"/>
	...

Résultat:

icon

L'icône est volontairement blanc car dans notre application, on a plutôt fait du "texte blanc sur fond noir" et pas l'inverse. Par la suite on changera ces couleurs.

Par défaut, l'icône est placé à gauche. Lors de la frappe dans Flash Builder, vous avez peut-être remarqué une autre propriété "iconPlacement":

iconp

Cela semble parfait, choisissons "right":

right

C'est mieux. Mais notre bouton ne prend pas toute la largeur et fait un peu tâche. On va lui donner une width="100%":

wid

Hum, ce n'est pas vraiment le résultat espéré. Tous les éléments sont centrés par défaut alors que l'on voudrait avoir une partie à gauche et l'autre à droite. Pour nos besoins, les propriétés par défaut sont presque suffisantes mais pas vraiment. On peut faire beaucoup avec les propriétés par défaut mais on ne peut pas tout faire. Pour faire exactement ce que l'on veut, il faut faire une Skin.

Skin par défaut de Button : ButtonSkin

Je le dis souvent (peut-être pas assez) mais la meilleure manière d'apprendre le Flex est de s'inspirer des meilleurs exemples, de leurs techniques. Et ou trouve-t-on les meilleurs exemples? Si vous vous dîtes sur flex-tutorial.fr, cela me fait plaisir mais pas vraiment ^^.

Vous avez déjà tout ce qu'il faut sous la main, dans le code du SDK Flex. Flex est open source, profitez-en! Pour avoir passé pas mal de temps à fouiner dans les classes du framework, je peux vous assurez que l'on y trouve souvent la réponse à ses questions.

Pour commencer, allons voir le fichier CSS qui associé au thème mobile par défaut. Celui-ci se trouve sur votre disque, sous Windows il est ici:

C:\Program Files (x86)\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\frameworks\projects\mobiletheme\defaults.css

Pour un système Mac, c'est à peu près pareil sauf qu'il faut remplacer le début par Application (enfin vous savez vous servir de votre Mac). Dans ce fichier, on va chercher "Button", pour voir les styles et skins associés par défaut au composant Button. On trouve rapidement:

Button{
    fontWeight: "bold";
    skinClass: ClassReference("spark.skins.mobile.ButtonSkin");
}

On apprend déjà que la skin par défaut de tous les Button est spark.skins.mobile.ButtonSkin. Bon avec un peu de bouteille, vous auriez pu deviner cela, il est assez conventionnel en Flex de rajouter "Skin" à la suite du nom du composant pour symboliser la skin par défaut.

Retournons dans Flash Builder. Utilisez le raccourci Ctrl+T qui va vous permettre de consulter n'importe quelle classe du framework Flex. Tapez donc ButtonSkin puis Entrée pour consulter le code de cette classe. Prenez bien celle qui est dans le package "mobile", sinon vous tomberez sur la skin de base du thème classique (non-mobile):

type

Prenez 2 minutes pour bien comprendre comment fonctionne cette classe.

Analyse rapide du code de la classe ButtonSkin

Première partie, le constructeur. On y effectue un traitement suivant les DPI de l'application (densité de pixels). Suivant la classe DPI de l'appareil, on assigne différentes valeurs à upBorderSkin et downBorderSkin et différentes valeurs de paddings:

switch (applicationDPI){
	case DPIClassification.DPI_320:{
		upBorderSkin = spark.skins.mobile320.assets.Button_up;
		downBorderSkin = spark.skins.mobile320.assets.Button_down;

		layoutGap = 10;
		layoutCornerEllipseSize = 20;
		layoutPaddingLeft = 20;
		layoutPaddingRight = 20;
		layoutPaddingTop = 20;
		layoutPaddingBottom = 20;
		layoutBorderSize = 2;
		measuredDefaultWidth = 64;
		measuredDefaultHeight = 86;

		break;
	}
	...

On reviendra plus tard dans ce fil rouge sur ces problématiques de DPI.

13juin/114

AIR Mobile – Application Pokémon (7) – Modifier le style de la liste

Dans le précédent tutorial, on a  vu comment filtrer notre liste de pokémons:

AIR Mobile – Application Pokémon (6) – Filtrer la liste des pokémons avec un champ de recherche

La liste est pour l'instant un peu morose, peu d'informations affichées et un thème de couleur très basique. Dans cette partie du tutorial, on va voir comment donner un peu plus de style à notre liste.

Utilisation du composant IconItemRenderer

De base, une liste Flex utilise le composant LabelItemRenderer qui n'affiche qu'une ligne de texte. Or, il en existe d'autres dans le SDK, notamment IconItemRenderer:

AIR Mobile – Les itemRenderer de List (LabelItemRenderer, IconItemRenderer, …)

Ces composants qui gèrent l'affichage de chaque ligne sont appelés "itemRenderer". Pour utiliser un iconRenderer différent de celui de base, il faut le définir comme valuer de la propriété "itemRenderer" du composant List. Un itemRenderer est un peu spécial car on va donner une référence vers un composant, il faudra donc encapsuler la déclaration dans une balise fx:Component. Notez que Flash Builder vous aidera beaucoup grâce à l'auto-complétion, apprenez à vous en servir à bon escient.

Pour définir un IconItemRenderer comme itemRenderer, vous allez entrer le code ci-dessous:

<s:List width="100%" height="100%" dataProvider="{_dp}" labelField="nom">
    <s:itemRenderer>
      <fx:Component>
        <s:IconItemRenderer />
      </fx:Component>
    </s:itemRenderer>
  </s:List>

Affichage d'une 2ème ligne de data

Le composant IconItemRenderer peut vous permettre d'afficher une deuxième ligne de donnée. Un peu comme on l'avait fait avec la propriété "labelField" de List, on va ici préciser un "messageField". Le "message" étant en fait la 2ème ligne.

Sur le composant IconItemRenderer, précisez que le messageField est "type", ce qui nous donnera le type du Pokemon. Lancer l'application pour obtenir ce résultat:

mess

Ajout d'un "decorator" en fin de ligne

Dans les prochaines étapes de ce tutorial, on va pouvoir naviguer depuis cette liste vers une fiche détaillée des capacités du pokémon. L'affichage de la fiche du pokémon se fait lorsque l'on sélectionne un pokémon dans la liste. Quand une action utilisateur est possible, il est souvent conseillé d'afficher un icône sur la droite de chaque élément, le plus souvent une puce ou une flèche.

Le composant IconItemRenderer étant bien pensé, celui-ci vous permet d'assigner un icône qui sera affiché sur la droite de chaque ligne. Cet icône peut être défini grâce à la propriété "decorator" du composant IconItemRenderer.

Dans la partie 2 (préparation de l'application), vous avez du télécharger un dossier nommé assets que vous avez mis dans votre projet. Celui-ci contient l'icône que l'on va ajouter, il doit maintenant être présent dans les sources de votre projet.

Remplis sous: Adobe Air, CSS, Styles Lire la suite
28mai/110

AIR Mobile – Modifier les styles du composant ActionBar

iEncore un article de Jason San José, que vous trouverez sur son blog:

http://blogs.adobe.com/jasonsj/2011/05/tutorial-styling-the-actionbar.html

Le dernier présentait comment modifier les styles d'une TabbedViewNavigatorApplication, celui là s'occupe de l'ActionBar de votre application. Il est donc valable pour les ViewNavigatorApplication et les TabbedViewNavigatorApplication qui utilisent toutes les 2 le composant ActionBar.

Vu que beaucoup est dit dans son article, je vais me contenter de reprendre ces éléments :)

La propriété chromeColor

On commence par le plus simple, la propriété chromeColor qui permet de définir la couleur de l'ActionBar (gris par défaut). Le style de l'ActionBar a un léger "gloss" qui sera conservé, quelle que soit la couleur choisie. Voici son exemple en rouge:

blog_ActionBar_chromeColor-300x98

Pour effectuer cette modification, il vous suffit d'ajouter un sélecteur de type sur s|ActionBar dans votre application et de définir la propriété CSS chromeColor comme ceci:

<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
firstView="views.holrHomeView">
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
 s|ActionBar
{
chromeColor: #990000;
}
</fx:Style>
</s:ViewNavigatorApplication>

Comme vous avez utilisé un sélecteur de type (et pas de classe), cette modification sera apportée à toutes les ActionBar de votre application.

La propriété titleAlign

L'alignement par défaut du titre de l'ActionBar se fait à gauche. Dans les interfaces de type iOS, le titre est plus souvent centré. Pour définir l'alignement du titre, encore une fois il suffit de modifier la valeur d'une propriété CSS nommée "titleAlign":

s|ActionBar
{
  chromeColor: #990000;
  titleAlign: center;
}

Les valeurs possibles sont "left", "center", "right". Voici le rendu pour "center":

blog_ActionBar_titleAlign-300x101

La propriété defaultButtonAppearance

Par défaut, le composant ActionBar assigne une Skin arbitraire pour tout composant Button intégré dans navigationContent (partie de gauche) et actionContent (partie de droite). De base, cette skin est assez "simple" dans le sens où elle n'a pas de contours.