Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Flex 4 en un jour - Composants Spark - Personnalisation

Compatible Flex 4. Cliquer pour en savoir plus sur les compatibilités.Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par tannoy (Antony Chauviré), le 22 novembre 2010

Cet article est une traduction d'un mini livre nommé Flex 4 in a Day de Mihai Corlan.

Adobe a donné son accord concernant la traduction de ce mini-livre.

Le contrat de personnalisation – Personnalisation des composants Spark

La séparation dans deux classes différentes de la logique métier et de l'apparence d'un composant est une bonne chose, mais s'il n'y a pas d'interactions entre ces classes, nous perdons une grand partie des interfaces riches. Imaginez une belle skin pour un bouton qui ne réagit pas aux événements de survol ou de clic.

Afin de permettre l'interactivité entre le composant et sa skin, il existe un contrat entre ces deux entités. Le contrat de personnalisation a ces trois composantes: données, parties, et états.

Prenons un simple composant Spark, comme un bouton et analysons ces composantes.

Les données

La classe de composant contient les données. Pour un bouton, ce pourrait être la légende (texte) du bouton:

[Bindable]
public function set label

La classe de skin définit un composant Label pour afficher les données sur l'écran. Il peut lire les données de la classe du composant en utilisant la variable hostComponent:

<s:Label text=“{hostComponent.label}/>

Les parties (parts)

La classe de composant définit les parties de la skin et si elles sont obligatoires ou optionnelles:

[SkinPart(required="false")]
public var labelDisplay:TextBase;

La classe de skin implémente ses parties (ou elle peut choisir de les ignorer si elle sont optionnelles):

<s:Label id=“labelDisplay”/>

Les états

La classe de composant définit les états qui sont supportés:

[SkinState(up)]
[SkinState(“over”)]
[SkinState(down)]
[SkinState(“disabled”)]

La classe de skin peut choisit ou non de réagir aux changements d 'états. Mais elle doit déclarer les états définis par le composant hôte:

<s:State name=“up”/>
<s:State name=“over”/>
<s:State name=“down”/>
<s:State name=“disabled”/>

Relations entre le composant et sa skin: vous pouvez définir une relation entre une classe de skin et le composant qui sera personnalisé avec elle. Vous pouvez ajouter à la classe de skin cette méta-données:

<fx:Metadata>
	[HostComponent("spark.components.Button")]
</fx:Metadata>

Création de composants et de skins

Vous avez deux méthodes pour créer un composant Spark et une skin:

  • Partir de rien; vous étendez les classes SkinnableComponent et Skin.
  • Etendre un composant Spark existant ou une skin existante.

Voici le code pour un composant personnalisé qui peut être utilisé pour afficher le status d'une connexion réseau.

Le code pour le composant:

package org.corlan
{
	import spark.components.supportClasses.SkinnableComponent;
	import spark.components.supportClasses.TextBase;
 
	//the states defined by the skin
	[SkinState("connected")]
	[SkinState("disconnected")]
	[SkinState("disabled")]
 
	public class ConnectionStatus extends SkinnableComponent
	{
		private var _content:String;
		private var _enabled:Boolean = true;
		private var _connected:Boolean = false;
		[SkinPart(required="true")]
		public var labelDisplay:TextBase;
		public function ConnectionStatus() {
			super();
		}
		public function set label(val:String):void {
			content = val;
		}
		public function get label():String {
			return (content != null) ? content.toString() : "";
		}
		public function set connected(val:Boolean):void {
			_connected = val;
			invalidateState();
		}
		public function get connected():Boolean {
			return _connected;
		}
		override public function set enabled(val:Boolean):void {
			_enabled = val;
			super.enabled = val;
		}
		private function set content(val:String):void {
			_content = val;
			21
			// Push to the optional labelDisplay skin part
			if (labelDisplay)
				labelDisplay.text = label;
		}
		private function get content():String {
			return _content;
		}
		override protected function partAdded(partName:String, instance:Object):void {
			super.partAdded(partName, instance);
			if (instance == labelDisplay) {
				// Push down to the part only if the label was explicitly set
				if (_content)
					labelDisplay.text = label;
			}
		}
		override protected function getCurrentSkinState():String {
			if (!_enabled)
				return "disabled";
			if (_connected)
				return "connected";
			else
				return "disconnected";
		}
		private function invalidateState():void {
			//invalidateProperties();
			invalidateSkinState();
		}
	}
}

Le code pour la classe de skin:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
			 alpha.disabled="0.5">
	<fx:Metadata>
		[HostComponent("org.corlan.ConnectionStatus")]
	</fx:Metadata>
	<s:states>
		<s:State name="disconnected"/>
		<s:State name="connected" />
		<s:State name="disabled" />
	</s:states>
	<s:Group>
		<s:layout>
			<s:HorizontalLayout/>
		</s:layout>
		<s:Label id="labelDisplay"
				 textAlign="center"
				 verticalAlign="middle"
				 maxDisplayedLines="1"
				 horizontalCenter="0"
				 verticalCenter="1"
				 color="#ff0000"
				 color.connected="#00ff00"/>
	</s:Group>
</s:SparkSkin>

Et vous pouvez utiliser ce composant comme ceci:

private function changeConnStatus():void
{
	connStatus.connected = ! connStatus.connected;
}
<corlan:ConnectionStatus id="connStatus"
	label="Connection Status"
	skinClass="org.corlan.ConnectionStatusSkin"/>

Cycle de vie de composants et de skins

Comment la classe de skin communique-t'elle avec la classe du composant ? La classe du composant doit implémenter la méthode getCurrentSkinState(). Cette méthode retourne l'état que la skin doit afficher. Quand vous voulez poussez les données dans la skin, vous appelez la méthode invalidateSkinState() de la classe du composant. À son tour, la skin fera appel à la méthode getCurrentSkinState() et va changer son état en conséquence.

Qu'en est-il de l'injection des données du composant vers la skin (par exemple la chaîne de l'étiquette d'un bouton) ? Il y a deux façons d'atteindre cet objectif. La skin peut extraire les données en utilisant la variable hostComponent. Ou l'objet composant peut pousser les données dans la ski, à l'aide des parties de skin (skinPart). Si vous souhaitez utiliser cette dernière méthode, vous devez ssurcharger la méthode partAdded() (vous pouvez voir cette approche utilisée dans l'exemple précédent).

Ressources

Exemple d'ajout d'un nouvel état à une skin d'un composant qui étend un composant existant:
Justin Shacklette’s Drawer Component in Flex 4

Pour plus d'information au sujet de la personnalisation (skinning):
Introducing skinning in Flex 4







Page précédente | Sommaire | Page suivante