Sur la route d'Oxiane digressions diverses

LeBlog OXiane

2 juin
2011

Développeurs graphistes chefs de projet assistantes

Une humble contribution à la compréhension du microcosme de l’informaticien !

L’article original duquel l’image est tirée, et à laquelle je n’ai rajouté que les lignes « assistantes » est ici.

 

Alain Boudard

aboudard

25 mai
2011

OXiane Studio : KiteSpirit.com

Créée en 2004, par Arnaud et Sébastien Murcia, 2 passionnés de sport de glisse, la société « Kite Spirit » est spécialisée dans la vente de matériel de kitesurf, et plus généralement, de sports de glisse.

Impliquée dans le E-commerce depuis 2005, la boutique « kite-spirit.com » développée à partir de la solution Os Commerce, fait aujourd’hui peau-neuve, et change de plate-forme, puisque c’est désormais sous Presta Shop qu’elle sera développée, la réalisation est assurée chez OXiane Studio par Alain Boudard.

Avec cette version plus moderne, la E-boutique devrait bénéficier d’un meilleur référencement, avec des pages plus lisibles pour les moteurs de recherche, une architecture, et une ergonomie très abouties.

L’interface  Prestashop permet de mettre en place des fonctions plus avancées, telles que la gestion des packs matériels, des bons de réduction, une version anglaise, et une présentation plus dynamique des fiches produits…

En 2011, Kite Spirit transfère également ses locaux du centre ville d’Auray, pour se retrouver en périphérie de la ville dans un magasin plus spacieux. La société a pour ambition d’augmenter ses stocks, tout en diversifiant l’offre de son catalogue, avec notamment l’arrivée du Stand Up Paddle Surf, une pratique émergente au sein de la famille des sports de glisse.

Alain Boudard

aboudard

4 mai
2011

Présentation OXiane sous Sencha Touch

Voici un petit aperçu de ce que l’on peut réaliser avec l’API Sencha Touch.

http://www.oxiane.com/touch/

Ici une mini application mobile avec un mélange de Javascript et de Media Queries pour adapter les slides à l’écran.

Même si je ne suis pas fan de l’API, il y a des choses intéressantes.

Il faut quand même s’habituer à ne pas coder de HTML du tout, par exemple.

var carousel1 = new Ext.Carousel({ ... }

Je préfère réellement l’API JQuery qui se situe plus en tant qu’inspecteur de code, plutôt qu’en tant que générateur, ou de pseudo-template. Mais chacun ses gouts ! Bientôt nous verrons cette même présentation avec quelques lignes de code JQuery. On profite de la sortie de la version 1.6 de cette API ;)

Alain Boudard

aboudard

26 avr
2011

Composants mobiles : Adobe CS5.5 et IBM se lancent

Depuis quelque semaines les news tombent. Le monde du développement mobile évolue très rapidement.

IBM sponsorise un projet open-source ambitieux : Maqetta. Le but : fournir un IDE complet et performant pour développer vos applications HTML5 / CSS3 ! Ambitieux étant donné la stabilité des specs qui n’en sont toujours pas à l’heure où on écrit ces lignes :) Contrairement à ce qu’on peut lire à droite à gauche, ce n’est pas du tout une alternative à Flash, au mieux ce serait un cousin de Flex / FlashBuilder, car le focus est mis sur la conception d’interface web complexe en se basant sur les outils reconnus que sont :

  • JQueryUI
  • Dojo (normal le projet est maintenu par dojofoundation)
  • YUI (Yahoo User Interface)

Il reste à installer le produit, pour l’instant je n’ai pas pu tester, c’est malheureusement un peu classique avec ce genre de « truc » open-source, il faut déjà être affuté pour comprendre comment ne serait-ce qu’installer le machin !

Pour l’instant, le concurrent de Flash est encore loin, mais il arrivera, et certainement via Adobe, qui sortait il y a peu la version 5.5 de sa Creative Suite, avec en particulier les outils de développement Mobile :

Le support de HTML5, les API mobiles avec en particulier l’intégration de JQuery Mobile dans Dreamweaver ! Le développement mobile rentre en phase « sérieuse », les outils en sont la marque.

Alain

Alain Boudard

aboudard

14 avr
2011

Composants perso réutilisables sous Android

Je suis en train de faire une petite maquette pour un client et je me rends compte qu’il y’a, comme dans la plupart des applis d’ailleurs, des éléments qui sont répétés plein de fois, avec des faibles variations. Par ex, un écran avec plusieurs sections, divisées par des titres qui ont presque tout en commun: police, taille, background, layout… Y’a seulement une icône qui change sur le côté et le texte, évidemment.

Le but de cet article est donc de montrer comment on peut faire du code réutilisable dans un layout Android. Le scénario d’utilisation de ce modèle, c’est un super développeur qui va créer des composants perso et les donner à une équipe de développeurs, qui n’auront qu’à drag & drop le composant sur leur layout et à remplir les propriétés.

Et là je me dis, mais attends, Android, ils ont pensé à tout, non, avec leur modèles en XML? et bien oui…
C’est comme en Swing mais plus simple à utiliser. En fait, ca ressemble à du « bon » vieux VB 6!

Voilà comment faire, en 4 étapes:

1) créer le modèle en XML: moi je veux donc un titre de section sur lequel on peut cliquer donc j’ai mis un Button. Et j’ai juste une ImageView en plus pour l’icone, sur la gauche. Comme on peut le remarquer, je n’ai pas mis la balise « src » pour l’imageview. La source de l’ImageView sera remplie plus tard.
Bon, pour compliquer un peu les choses, j’ai rajouté un RelativeLayout (celui qui a l’id = panel) en dessous en visibility GONE. Je m’en servirai après pour rajouter des éléments à mon item générique.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/custom">
  <Button android:id="@+id/BTN"
  	android:layout_width="fill_parent"
  	android:layout_height="wrap_content"
  	android:background="#FF0000"
  	android:text=""
  	android:textColor="@color/gris_bg"
  	android:layout_alignBaseline="@+id/IMG"
	android:layout_alignTop="@+id/IMG"
	android:layout_alignBottom="@+id/IMG"
	android:layout_marginTop="12sp"
	android:layout_marginBottom="12sp"/>
	<RelativeLayout android:id="@+id/panel"
		android:layout_below="@id/BTN"
		android:visibility="gone"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		>
	</RelativeLayout>
  <ImageView android:id="@+id/IMG"
  	android:layout_width="wrap_content"
  	android:layout_height="wrap_content"
  	android:background="@android:color/transparent"
  	android:layout_alignParentTop="true"
  	android:layout_marginTop="20sp"
  	android:layout_marginLeft="20sp"
  	android:layout_marginBottom="20sp"/>
</RelativeLayout>

note: mon fichier s’appelle customtitle.xml et se trouve dans res/layout

2) Je crée une définition des attributs pour mon modèle. Moi je veux juste changer le texte du Button et le drawable de l’imageview. Ce sont les « variables » que j’utiliserai dans mon composant perso. Donc j’ai juste besoin d’une String pour le texte du bouton et d’un champs Drawable pour la « source » de mon ImageView:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="stylableTitle">
        <attr name="txt" format="string"/>
        <attr name="android:drawable"/>
    </declare-styleable>
</resources>

Ca c’est le contenu de mon fichier res/values/attrs.xml qui contient, comme son nom l’indique, une liste d’attributs.

3) Je crée une classe qui va faire la correspondance entre les attributs (étape 2) et mon layout modèle (étape 1). En gros, il s’agit de demander à Android de créer une instance de mon modèle XML, puis de remplir les champs text et src de mes composants TextView et ImageView.

public class CustomTitle extends RelativeLayout{
	private Button button;
	private ImageView img;

	public CustomTitle(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context,attrs);
	}
        // ce constructeur ne devrait jamais être appelé, car il n'a pas d'AttributeSet en paramètre.
	public CustomTitle(Context context) {
		super(context);
	}
	public CustomTitle(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context,attrs);
	}

	private void init(Context ctx, AttributeSet attrs){  

      // inflation du modèle "customtitle", et initialisation des composants Button et ImageView
      // on cherche le service Android pour instancier des vues
		LayoutInflater li = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      // on instancie notre vue customisée (celle créée dans l'étape 1, qui se trouve dans res/layout/customtitle)
		View v = li.inflate(R.layout.customtitle, null);
		button = (Button)v.findViewById(R.id.BTN);
		img = (ImageView)v.findViewById(R.id.IMG);
		addView(v);

      // Le modèle est chargé, on a plus qu'à l'initialiser avec les attributs qu'on a reçus en paramètre

	TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.stylableTitle);

      // on obtient un TypedArray, une classe qui a plein de méthodes getString(int index),
      // getInteger(int index) (...) pour obtenir la valeur String, Integer (...) d'un attribut.

      // on vérifie que l'attribut "txt" n'est pas null: ce test est important! on verra par la suite pourquoi
	if(a.getString(R.styleable.stylableTitle_txt)!=null)
	        button.setText(a.getString(R.styleable.stylableTitle_txt));

      // et on recommence pour l'attribut "drawable"
	if(a.getDrawable(R.styleable.stylableTitle_android_drawable)!=null)
	        img.setBackgroundDrawable(a.getDrawable(R.styleable.stylableTitle_android_drawable));

      // on recycle, c'est pour sauver mère nature
	        a.recycle();
	}
}

Ici, j’ai simplement généré une classe qui étend un Layout (j’ai choisi RelativeLayout), en générant bien les constructeurs qui reçoivent un AttributeSet! Et j’appelle une méthode init() qui va « inflater » mon layout générique, récupérer les ID’s du button et de l’imageView. Le addView(v) permet d’ajouter la vue « inflatée » à « this », c’est à dire au RelativeLayout.

Dans un deuxième temps, je vais chercher dans les attributs les valeurs que je veux mettre dans chacun de mes composants. On reçoit en fait en paramètre un AttributeSet (attrs), qui contient une collection d’attributs. Il suffit d’extraire de cette liste tous les attributs qui nous intéressent, c’est à dire ceux qu’on a défini dans le fichier attrs.xml sous le nom « stylableTitle ». C’est fait avec la méthode obtainStyledAttributes.

Une fois qu’on a bien trouvé les attributs qu’on veut, on fait des setText() et setBackgroundDrawable() avec les valeurs des attributs, pour initialiser le modèle.

note: les valeurs R.styleable.* sont générées automatiquement

4) A ce stade, c’est presque fini, il ne reste plus qu’à utiliser ce qu’on a fait!
Dans un fichier de layout, il suffit d’écrire:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res/com.test"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
  <com.test.views.CustomTitle
  	android:layout_width="match_parent"
  	android:layout_height="wrap_content"
  	android:drawable="@drawable/l_icone_de_mon_titre"
  	app:txt="le texte de mon titre"
  />
</RelativeLayout>

Ici, il y’a plusieurs subtilités, mais il faut d’abord regarder le principal: j’ai inséré une balise com.test.views.CustomTitle. Android va, comme pour toutes les autres balises de base, aller instancier la classe java qui correspond (donc ici, la notre qu’on a créé dans l’étape 2). Et j’ai rajouté à cette balise quelques attributs, pour la personnaliser un peu. layout_width et height, on connait. Je lui ai mis un attribut android:drawable, qui sera donc passé dans le constructeur public CustomTitle(Context context, AttributeSet attrs) {}, qui lui même va appeler la méthode init(), et on ira chercher l’attribut drawable pour le mettre en background de l’imageview du modèle, comme expliqué précédemment.

  • Une petite subtilité, c’est l’utilisation de la balise « app:txt ». En fait, pour l’exercice, j’ai exprès mis dans ma feuille d’attributs un nom de balise inconnu par Android. Il n’y a pas de balise android:txt! Pour que cette balise puisse être utilisée, j’ai donc rajouté le namespace de mon projet sur le composant parent.
    C’est la ligne xmlns:app= »http://schemas.android.com/apk/res/com.test »
    Elle indique que pour toutes les balises « app:XXXX », on cherche dans le package « com.test ». D’ailleurs, comme android:txt n’existe pas, il faut aussi lui préciser son type quand on la déclare ( ). Pour info, les formats disponibles sont:
    Reference, String, Color, Dimension, Boolean, Integer, Float, Fraction, Enum, Flag
    A ma connaissance, on ne peut pas ajouter de type de format! J’imaginais déjà un pattern où on donne directement un objet métier dans un attribut, une formation par exemple, et il remplit tout seul chacun des champs (le titre de la formation, l’url etc). On devra donc se contenter de faire des balises app:titreFormation, app:url, pour chacun des champs qu’on veut remplir.
  • Et comme il existe déjà une balise « android:drawable » qui contient un drawable dans le package « android », pas besoin de redéfinir celui là! J’aurais bien sur pu utiliser « android:text » ou même « android:src » pour afficher mon texte sur mon button. Mais ça n’aurait pas été aussi drôle, non?
    Ce système permet donc d’ajouter autant d’attributs qu’on veut, avec des noms intuitifs. Par exemple, on peut très bien imaginer de compliquer un peu le modèle en faisant une page entière qui aurait des attributs « body », « title », ou même une URL sur laquelle on irait chercher des infos.

  • Une autre subtilité, c’est qu’on peut très bien oublier un des attributs, ou lui donner une valeur qui n’a pas de sens. C’est pourquoi il vaut toujours mieux tester au niveau de la classe java la valeur des attributs. Pour le développeur qui va utiliser le composant, il est tout à fait possible de ne pas renseigner de valeur pour l’attribut « txt », ou même de ne pas écrire cet attribut du tout! Comme chacun sait, écrire setText(null) n’est pas recommandé!

Attention cependant, systématiquement tout faire passer dans les attributs n’est pas une bonne solution. On en perdrait l’intérêt original de ce procédé: généraliser ce qui est généralisable.
A l’utilisation, l’intérêt pour le développeur se voit cependant très rapidement. Si un élément se répète de nombreuses fois, éventuellement sur plusieurs pages, on n’a besoin de le modifier qu’à un seul endroit lorsqu’untel nous dit que « finalement, je veux le fonds en bleu et l’image alignée à droite »!

Et la prochaine fois, j’expliquerai pourquoi mon modèle n’aurait pas du être un <RelativeLayout>, mais plutôt un <merge> ! Quoiqu’en fait, il suffit de lire cet article ici.

En revanche, la prochaine fois, j’expliquerai comment savoir si on doit faire un <include> ou un composant perso comme expliqué ci dessus.

Johann Hilbold

jhilbold